550 lines
15 KiB
C
550 lines
15 KiB
C
/*++
|
||
|
||
Copyright (c) 1991 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
ixusage.c
|
||
|
||
Abstract:
|
||
|
||
Author:
|
||
|
||
Ken Reneris (kenr)
|
||
|
||
Environment:
|
||
|
||
Kernel mode only.
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "halp.h"
|
||
#include "kdcom.h"
|
||
|
||
//
|
||
// Array to remember hal's IDT usage
|
||
//
|
||
|
||
extern ADDRESS_USAGE *HalpAddressUsageList;
|
||
extern IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR];
|
||
extern WCHAR HalpSzSystem[];
|
||
extern WCHAR HalpSzSerialNumber[];
|
||
extern KAFFINITY HalpActiveProcessors;
|
||
|
||
PUCHAR KdComPortInUse = NULL;
|
||
|
||
ADDRESS_USAGE HalpComIoSpace = {
|
||
NULL, CmResourceTypePort, DeviceUsage,
|
||
{
|
||
0x2F8, 0x8, // Default is 2F8 for COM2. This will be changed.
|
||
0, 0
|
||
}
|
||
};
|
||
|
||
VOID
|
||
HalpGetResourceSortValue (
|
||
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
|
||
OUT PULONG sortscale,
|
||
OUT PLARGE_INTEGER sortvalue
|
||
);
|
||
|
||
USHORT HalpComPortIrqMapping[5][2] = {
|
||
{COM1_PORT, 4},
|
||
{COM2_PORT, 3},
|
||
{COM3_PORT, 4},
|
||
{COM4_PORT, 3},
|
||
{0,0}
|
||
};
|
||
|
||
VOID
|
||
HalpReportSerialNumber (
|
||
VOID
|
||
);
|
||
|
||
#ifdef ALLOC_PRAGMA
|
||
#pragma alloc_text(INIT,HalpRegisterVector)
|
||
#pragma alloc_text(INIT,HalpGetResourceSortValue)
|
||
#pragma alloc_text(INIT,HalpReportResourceUsage)
|
||
#pragma alloc_text(INIT,HalpReportSerialNumber)
|
||
#endif
|
||
|
||
|
||
|
||
|
||
VOID
|
||
HalpRegisterVector (
|
||
IN UCHAR ReportFlags,
|
||
IN ULONG BusInterruptVector,
|
||
IN ULONG SystemInterruptVector,
|
||
IN KIRQL SystemIrql
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This registers an IDT vectors usage by the HAL.
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
|
||
--*/
|
||
{
|
||
#if DBG
|
||
// There are only 0ff IDT entries...
|
||
ASSERT (SystemInterruptVector <= MAXIMUM_IDTVECTOR &&
|
||
BusInterruptVector <= MAXIMUM_IDTVECTOR);
|
||
#endif
|
||
|
||
//
|
||
// Remember which vector the hal is connecting so it can be reported
|
||
// later on
|
||
//
|
||
|
||
HalpIDTUsage[SystemInterruptVector].Flags = ReportFlags;
|
||
HalpIDTUsage[SystemInterruptVector].Irql = SystemIrql;
|
||
HalpIDTUsage[SystemInterruptVector].BusReleativeVector = (UCHAR) BusInterruptVector;
|
||
}
|
||
|
||
|
||
VOID
|
||
HalpGetResourceSortValue (
|
||
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
|
||
OUT PULONG sortscale,
|
||
OUT PLARGE_INTEGER sortvalue
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Used by HalpReportResourceUsage in order to properly sort
|
||
partial_resource_descriptors.
|
||
|
||
Arguments:
|
||
|
||
pRCurLoc - resource descriptor
|
||
|
||
Return Value:
|
||
|
||
sortscale - scaling of resource descriptor for sorting
|
||
sortvalue - value to sort on
|
||
|
||
|
||
--*/
|
||
{
|
||
switch (pRCurLoc->Type) {
|
||
case CmResourceTypeInterrupt:
|
||
*sortscale = 0;
|
||
*sortvalue = RtlConvertUlongToLargeInteger(
|
||
pRCurLoc->u.Interrupt.Level );
|
||
break;
|
||
|
||
case CmResourceTypePort:
|
||
*sortscale = 1;
|
||
*sortvalue = pRCurLoc->u.Port.Start;
|
||
break;
|
||
|
||
case CmResourceTypeMemory:
|
||
*sortscale = 2;
|
||
*sortvalue = pRCurLoc->u.Memory.Start;
|
||
break;
|
||
|
||
default:
|
||
*sortscale = 4;
|
||
*sortvalue = RtlConvertUlongToLargeInteger (0);
|
||
break;
|
||
}
|
||
}
|
||
|
||
|
||
VOID
|
||
HalpReportResourceUsage (
|
||
IN PUNICODE_STRING HalName,
|
||
IN INTERFACE_TYPE DeviceInterfaceToUse
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
|
||
--*/
|
||
{
|
||
PCM_RESOURCE_LIST RawResourceList, TranslatedResourceList;
|
||
PCM_FULL_RESOURCE_DESCRIPTOR pRFullDesc, pTFullDesc;
|
||
PCM_PARTIAL_RESOURCE_LIST pRPartList, pTPartList;
|
||
PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc, pTCurLoc;
|
||
PCM_PARTIAL_RESOURCE_DESCRIPTOR pRSortLoc, pTSortLoc;
|
||
CM_PARTIAL_RESOURCE_DESCRIPTOR RPartialDesc, TPartialDesc;
|
||
ULONG i, j, k, ListSize, Count;
|
||
ULONG curscale, sortscale;
|
||
UCHAR pass, reporton;
|
||
INTERFACE_TYPE interfacetype;
|
||
ULONG CurrentIDT, CurrentElement;
|
||
ADDRESS_USAGE *CurrentAddress;
|
||
LARGE_INTEGER curvalue, sortvalue;
|
||
|
||
//
|
||
// Claim the debugger com port resource if it is in use
|
||
//
|
||
if (KdComPortInUse != NULL) {
|
||
HalpComIoSpace.Element[0].Start = (ULONG)(ULONG_PTR)KdComPortInUse;
|
||
HalpRegisterAddressUsage(&HalpComIoSpace);
|
||
|
||
//
|
||
// The debugger does not use any interrupts. However for consistent
|
||
// behaviour between a machine with and without a debugger, we claim
|
||
// an interrupt for the debugger if the debugger port address is one
|
||
// for COM1-4.
|
||
//
|
||
|
||
for (i = 0; HalpComPortIrqMapping[i][0]; i++) {
|
||
|
||
if ((PUCHAR)HalpComPortIrqMapping[i][0] == KdComPortInUse) {
|
||
|
||
HalpRegisterVector( DeviceUsage | InterruptLatched,
|
||
HalpComPortIrqMapping[i][1],
|
||
HalpComPortIrqMapping[i][1] +
|
||
PRIMARY_VECTOR_BASE,
|
||
HIGH_LEVEL);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
//
|
||
// Allocate some space to build the resource structure
|
||
//
|
||
|
||
RawResourceList = (PCM_RESOURCE_LIST)ExAllocatePoolWithTag(
|
||
NonPagedPool,
|
||
PAGE_SIZE*2,
|
||
HAL_POOL_TAG);
|
||
TranslatedResourceList = (PCM_RESOURCE_LIST)ExAllocatePoolWithTag(
|
||
NonPagedPool,
|
||
PAGE_SIZE*2,
|
||
HAL_POOL_TAG);
|
||
if (!RawResourceList || !TranslatedResourceList) {
|
||
|
||
//
|
||
// These allocations were critical.
|
||
//
|
||
|
||
KeBugCheckEx(HAL_MEMORY_ALLOCATION,
|
||
PAGE_SIZE*4,
|
||
1,
|
||
(UINT_PTR)__FILE__,
|
||
__LINE__
|
||
);
|
||
}
|
||
|
||
//
|
||
// This functions assumes unset fields are zero
|
||
//
|
||
|
||
RtlZeroMemory(RawResourceList, PAGE_SIZE*2);
|
||
RtlZeroMemory(TranslatedResourceList, PAGE_SIZE*2);
|
||
|
||
//
|
||
// Initialize the lists
|
||
//
|
||
|
||
RawResourceList->List[0].InterfaceType = (INTERFACE_TYPE) -1;
|
||
|
||
pRFullDesc = RawResourceList->List;
|
||
pRCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) RawResourceList->List;
|
||
pTCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) TranslatedResourceList->List;
|
||
|
||
|
||
|
||
for(pass=0; pass < 2; pass++) {
|
||
if (pass == 0) {
|
||
//
|
||
// First pass - build resource lists for resources reported
|
||
// reported against device usage.
|
||
//
|
||
|
||
reporton = DeviceUsage & ~IDTOwned;
|
||
interfacetype = DeviceInterfaceToUse;
|
||
} else {
|
||
|
||
//
|
||
// Second pass = build reousce lists for resources reported
|
||
// as internal usage.
|
||
//
|
||
|
||
reporton = InternalUsage & ~IDTOwned;
|
||
interfacetype = Internal;
|
||
}
|
||
|
||
CurrentIDT = 0;
|
||
CurrentElement = 0;
|
||
CurrentAddress = HalpAddressUsageList;
|
||
|
||
for (; ;) {
|
||
if (CurrentIDT <= MAXIMUM_IDTVECTOR) {
|
||
//
|
||
// Check to see if CurrentIDT needs to be reported
|
||
//
|
||
|
||
if (!(HalpIDTUsage[CurrentIDT].Flags & reporton)) {
|
||
// Don't report on this one
|
||
CurrentIDT++;
|
||
continue;
|
||
}
|
||
|
||
//
|
||
// Report CurrentIDT resource
|
||
//
|
||
|
||
RPartialDesc.Type = CmResourceTypeInterrupt;
|
||
RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
|
||
RPartialDesc.Flags =
|
||
HalpIDTUsage[CurrentIDT].Flags & InterruptLatched ?
|
||
CM_RESOURCE_INTERRUPT_LATCHED :
|
||
CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
|
||
RPartialDesc.u.Interrupt.Vector = HalpIDTUsage[CurrentIDT].BusReleativeVector;
|
||
RPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].BusReleativeVector;
|
||
RPartialDesc.u.Interrupt.Affinity = HalpActiveProcessors;
|
||
|
||
RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc);
|
||
TPartialDesc.u.Interrupt.Vector = CurrentIDT;
|
||
TPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].Irql;
|
||
|
||
CurrentIDT++;
|
||
|
||
} else {
|
||
//
|
||
// Check to see if CurrentAddress needs to be reported
|
||
//
|
||
|
||
if (!CurrentAddress) {
|
||
break; // No addresses left
|
||
}
|
||
|
||
if (!(CurrentAddress->Flags & reporton)) {
|
||
// Don't report on this list
|
||
CurrentElement = 0;
|
||
CurrentAddress = CurrentAddress->Next;
|
||
continue;
|
||
}
|
||
|
||
if (!CurrentAddress->Element[CurrentElement].Length) {
|
||
// End of current list, go to next list
|
||
CurrentElement = 0;
|
||
CurrentAddress = CurrentAddress->Next;
|
||
continue;
|
||
}
|
||
|
||
//
|
||
// Report CurrentAddress
|
||
//
|
||
|
||
RPartialDesc.Type = (UCHAR) CurrentAddress->Type;
|
||
RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
|
||
|
||
if (RPartialDesc.Type == CmResourceTypePort) {
|
||
i = 1; // address space port
|
||
RPartialDesc.Flags = CM_RESOURCE_PORT_IO;
|
||
} else {
|
||
i = 0; // address space memory
|
||
RPartialDesc.Flags = CM_RESOURCE_MEMORY_READ_WRITE;
|
||
}
|
||
|
||
// Notice: assuming u.Memory and u.Port have the same layout
|
||
RPartialDesc.u.Memory.Start.HighPart = 0;
|
||
RPartialDesc.u.Memory.Start.LowPart =
|
||
CurrentAddress->Element[CurrentElement].Start;
|
||
|
||
RPartialDesc.u.Memory.Length =
|
||
CurrentAddress->Element[CurrentElement].Length;
|
||
|
||
// translated address = Raw address
|
||
RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc);
|
||
HalTranslateBusAddress (
|
||
interfacetype, // device bus or internal
|
||
0, // bus number
|
||
RPartialDesc.u.Memory.Start, // source address
|
||
&i, // address space
|
||
&TPartialDesc.u.Memory.Start ); // translated address
|
||
|
||
if (RPartialDesc.Type == CmResourceTypePort && i == 0) {
|
||
TPartialDesc.Flags = CM_RESOURCE_PORT_MEMORY;
|
||
}
|
||
|
||
CurrentElement++;
|
||
}
|
||
|
||
//
|
||
// Include the current resource in the HALs list
|
||
//
|
||
|
||
if (pRFullDesc->InterfaceType != interfacetype) {
|
||
//
|
||
// Interface type changed, add another full section
|
||
//
|
||
|
||
RawResourceList->Count++;
|
||
TranslatedResourceList->Count++;
|
||
|
||
pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc;
|
||
pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc;
|
||
|
||
pRFullDesc->InterfaceType = interfacetype;
|
||
pTFullDesc->InterfaceType = interfacetype;
|
||
|
||
pRPartList = &pRFullDesc->PartialResourceList;
|
||
pTPartList = &pTFullDesc->PartialResourceList;
|
||
|
||
//
|
||
// Bump current location pointers up
|
||
//
|
||
pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
|
||
pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
|
||
}
|
||
|
||
|
||
pRPartList->Count++;
|
||
pTPartList->Count++;
|
||
RtlCopyMemory (pRCurLoc, &RPartialDesc, sizeof RPartialDesc);
|
||
RtlCopyMemory (pTCurLoc, &TPartialDesc, sizeof TPartialDesc);
|
||
|
||
pRCurLoc++;
|
||
pTCurLoc++;
|
||
}
|
||
}
|
||
|
||
ListSize = (ULONG) ( ((PUCHAR) pRCurLoc) - ((PUCHAR) RawResourceList) );
|
||
|
||
//
|
||
// The HAL's resource usage structures have been built
|
||
// Sort the partial lists based on the Raw resource values
|
||
//
|
||
|
||
pRFullDesc = RawResourceList->List;
|
||
pTFullDesc = TranslatedResourceList->List;
|
||
|
||
for (i=0; i < RawResourceList->Count; i++) {
|
||
|
||
pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
|
||
pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
|
||
Count = pRFullDesc->PartialResourceList.Count;
|
||
|
||
for (j=0; j < Count; j++) {
|
||
HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
|
||
|
||
pRSortLoc = pRCurLoc;
|
||
pTSortLoc = pTCurLoc;
|
||
|
||
for (k=j; k < Count; k++) {
|
||
HalpGetResourceSortValue (pRSortLoc, &sortscale, &sortvalue);
|
||
|
||
if (sortscale < curscale ||
|
||
(sortscale == curscale &&
|
||
RtlLargeIntegerLessThan (sortvalue, curvalue)) ) {
|
||
|
||
//
|
||
// Swap the elements..
|
||
//
|
||
|
||
RtlCopyMemory (&RPartialDesc, pRCurLoc, sizeof RPartialDesc);
|
||
RtlCopyMemory (pRCurLoc, pRSortLoc, sizeof RPartialDesc);
|
||
RtlCopyMemory (pRSortLoc, &RPartialDesc, sizeof RPartialDesc);
|
||
|
||
// swap translated descriptor as well
|
||
RtlCopyMemory (&TPartialDesc, pTCurLoc, sizeof TPartialDesc);
|
||
RtlCopyMemory (pTCurLoc, pTSortLoc, sizeof TPartialDesc);
|
||
RtlCopyMemory (pTSortLoc, &TPartialDesc, sizeof TPartialDesc);
|
||
|
||
// get new curscale & curvalue
|
||
HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
|
||
}
|
||
|
||
pRSortLoc++;
|
||
pTSortLoc++;
|
||
}
|
||
|
||
pRCurLoc++;
|
||
pTCurLoc++;
|
||
}
|
||
|
||
pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc;
|
||
pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc;
|
||
}
|
||
|
||
|
||
//
|
||
// Inform the IO system of our resources..
|
||
//
|
||
|
||
IoReportHalResourceUsage (
|
||
HalName,
|
||
RawResourceList,
|
||
TranslatedResourceList,
|
||
ListSize
|
||
);
|
||
|
||
ExFreePool (RawResourceList);
|
||
ExFreePool (TranslatedResourceList);
|
||
|
||
//
|
||
// Add system's serial number
|
||
//
|
||
|
||
HalpReportSerialNumber ();
|
||
}
|
||
|
||
VOID
|
||
HalpReportSerialNumber (
|
||
VOID
|
||
)
|
||
{
|
||
OBJECT_ATTRIBUTES objectAttributes;
|
||
UNICODE_STRING unicodeString;
|
||
HANDLE hSystem;
|
||
NTSTATUS status;
|
||
|
||
if (!HalpSerialLen) {
|
||
return ;
|
||
}
|
||
|
||
//
|
||
// Open HKEY_LOCAL_MACHINE\Hardware\Description\System
|
||
//
|
||
|
||
RtlInitUnicodeString (&unicodeString, HalpSzSystem);
|
||
InitializeObjectAttributes (
|
||
&objectAttributes,
|
||
&unicodeString,
|
||
OBJ_CASE_INSENSITIVE,
|
||
NULL, // handle
|
||
NULL
|
||
);
|
||
|
||
|
||
status = ZwOpenKey (&hSystem, KEY_READ | KEY_WRITE, &objectAttributes);
|
||
if (NT_SUCCESS(status)) {
|
||
|
||
//
|
||
// Add "Serial Number" as REG_BINARY
|
||
//
|
||
|
||
RtlInitUnicodeString (&unicodeString, HalpSzSerialNumber);
|
||
|
||
ZwSetValueKey (
|
||
hSystem,
|
||
&unicodeString,
|
||
0L,
|
||
REG_BINARY,
|
||
HalpSerialNumber,
|
||
HalpSerialLen
|
||
);
|
||
|
||
ZwClose (hSystem);
|
||
}
|
||
}
|