NT4/private/ntos/nthals/halalcor/alpha/iousage.c
2020-09-30 17:12:29 +02:00

648 lines
14 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
iousage.c
Abstract:
Author:
Ken Reneris (kenr)
Environment:
Kernel mode only.
Revision History:
Chao Chen 1-25-1995
--*/
#include "halp.h"
#include "iousage.h"
//
// Externals.
//
extern KAFFINITY HalpActiveProcessors;
//
// Private resource list.
//
static PBUS_USAGE HalpBusUsageList = NULL;
static PRESOURCE_USAGE HalpResourceUsageList = NULL;
//
// Default HAL name.
//
#define MAX_NAME_LENGTH 256
UCHAR HalRegisteredName[MAX_NAME_LENGTH] = "Alpha Compatible PCI/EISA/ISA HAL";
//
// Function prototype.
//
VOID
HalpReportResourceUsage (
IN PUNICODE_STRING HalName
);
VOID
HalpGetResourceSortValue (
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
OUT PULONG sortscale,
OUT PLARGE_INTEGER sortvalue
);
//
// Pragma stuff.
//
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT,HalpRegisterHalName)
#pragma alloc_text(INIT,HalpRegisterBusUsage)
#pragma alloc_text(INIT,HalpRegisterResourceUsage)
#pragma alloc_text(INIT,HalReportResourceUsage)
#pragma alloc_text(INIT,HalpReportResourceUsage)
#pragma alloc_text(INIT,HalpGetResourceSortValue)
#endif
//
// Function definitions.
//
VOID
HalpRegisterHalName(
IN PUCHAR NewHalName
)
/*++
Routine Description:
Allow the HAL to register a name string.
Arguments:
HalName - Supplies a pointer to the HAL name to register.
Return Value:
None.
--*/
{
strncpy( HalRegisteredName, NewHalName, MAX_NAME_LENGTH );
return;
}
VOID
HalpRegisterBusUsage (
IN INTERFACE_TYPE BusType
)
/*++
Routine Description:
Register the different bus types in the system.
Arguments:
BusType - bus type that requires registering.
Return Value:
None.
--*/
{
PBUS_USAGE Temp;
//
// Allocate the buffer to store the bus information.
//
Temp = (PBUS_USAGE)ExAllocatePool(NonPagedPool, sizeof(BUS_USAGE));
//
// Save the bus type.
//
Temp->BusType = BusType;
//
// Add the bus type to the head of the list.
//
Temp->Next = HalpBusUsageList;
HalpBusUsageList = Temp;
}
VOID
HalpRegisterResourceUsage (
IN PRESOURCE_USAGE Resource
)
/*++
Routine Description:
Register the resources used internally by the HAL to the I/O system.
Arguments:
Resource - resource that requires registering.
Return Value:
None.
--*/
{
PRESOURCE_USAGE Temp;
//
// Allocate the buffer to store the resource information.
//
Temp = (PRESOURCE_USAGE)ExAllocatePool(NonPagedPool, sizeof(RESOURCE_USAGE));
//
// Copy the resource to the buffer we allocated.
//
RtlCopyMemory(Temp, Resource, sizeof(RESOURCE_USAGE));
//
// Add the resource to the head of the resource list.
//
Temp->Next = HalpResourceUsageList;
HalpResourceUsageList = Temp;
}
VOID
HalReportResourceUsage (
VOID
)
/*++
Routine Description:
Report the resources used internally by the HAL to the I/O system.
Arguments:
None.
Return Value:
None.
--*/
{
ANSI_STRING AHalName;
UNICODE_STRING UHalName;
//
// Convert the string.
//
RtlInitAnsiString (&AHalName, HalRegisteredName);
RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE);
//
// Report the resources registered as in use by the HAL.
//
HalpReportResourceUsage(&UHalName);
RtlFreeUnicodeString(&UHalName);
}
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->QuadPart = 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;
case CmResourceTypeDma:
*sortscale = 3;
sortvalue->QuadPart = pRCurLoc->u.Dma.Channel;
break;
default:
*sortscale = 4;
sortvalue->QuadPart = 0;
break;
}
}
VOID
HalpReportResourceUsage (
IN PUNICODE_STRING HalName
)
/*++
Routine Description:
This routine registers the resources for the hal.
Arguments:
HalName - the name of the hal to be registered.
Return Value:
None.
--*/
{
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;
LARGE_INTEGER curvalue, sortvalue;
PHYSICAL_ADDRESS PhyAddress;
PBUS_USAGE CurrentBus;
PRESOURCE_USAGE CurrentResource;
//
// Allocate some space to build the resource structure.
//
RawResourceList=
(PCM_RESOURCE_LIST)ExAllocatePool(NonPagedPool, PAGE_SIZE*2);
TranslatedResourceList=
(PCM_RESOURCE_LIST)ExAllocatePool(NonPagedPool, PAGE_SIZE*2);
//
// 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;
//
// Report all the HAL resources.
//
CurrentBus = HalpBusUsageList;
while (CurrentBus) {
//
// Start at the head of the resource list for each bus type.
//
CurrentResource = HalpResourceUsageList;
while (CurrentResource) {
//
// Register the resources for a particular bus.
//
if (CurrentBus->BusType == CurrentResource->BusType) {
switch (CurrentResource->ResourceType) {
case CmResourceTypeInterrupt:
//
// Process interrupt resources.
//
RPartialDesc.Type = CmResourceTypeInterrupt;
RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
if (CurrentResource->u.InterruptMode == Latched)
RPartialDesc.Flags = CM_RESOURCE_INTERRUPT_LATCHED;
else
RPartialDesc.Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
RPartialDesc.u.Interrupt.Vector =
CurrentResource->u.BusInterruptVector;
RPartialDesc.u.Interrupt.Level =
CurrentResource->u.BusInterruptVector;
RPartialDesc.u.Interrupt.Affinity = HalpActiveProcessors;
RtlCopyMemory(&TPartialDesc, &RPartialDesc, sizeof(TPartialDesc));
TPartialDesc.u.Interrupt.Vector =
CurrentResource->u.SystemInterruptVector;
TPartialDesc.u.Interrupt.Level =
CurrentResource->u.SystemIrql;
break;
case CmResourceTypePort:
case CmResourceTypeMemory:
//
// Process port and memory resources.
//
RPartialDesc.Type = CurrentResource->ResourceType;
RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
if (RPartialDesc.Type == CmResourceTypePort) {
//
// In IO space.
//
i = 1;
RPartialDesc.Flags = CM_RESOURCE_PORT_IO;
} else {
//
// In memory space.
//
i = 0;
RPartialDesc.Flags = CM_RESOURCE_MEMORY_READ_WRITE;
}
//
// Notice: assume u.Memory and u.Port have the same layout.
//
RPartialDesc.u.Memory.Start.HighPart = 0;
RPartialDesc.u.Memory.Start.LowPart = CurrentResource->u.Start;
RPartialDesc.u.Memory.Length = CurrentResource->u.Length;
RtlCopyMemory(&TPartialDesc, &RPartialDesc, sizeof(TPartialDesc));
//
// Translate the address.
//
HalTranslateBusAddress(CurrentResource->BusType,
CurrentResource->BusNumber,
RPartialDesc.u.Memory.Start,
&i,
&PhyAddress );
TPartialDesc.u.Memory.Start = PhyAddress;
if ((RPartialDesc.Type == CmResourceTypePort) && (i == 0))
TPartialDesc.Flags = CM_RESOURCE_PORT_MEMORY;
break;
case CmResourceTypeDma:
//
// Process dma resources.
//
RPartialDesc.Type = CmResourceTypeDma;
RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
RPartialDesc.u.Dma.Channel = CurrentResource->u.DmaChannel;
RPartialDesc.u.Dma.Port = CurrentResource->u.DmaPort;
RtlCopyMemory(&TPartialDesc, &RPartialDesc, sizeof(TPartialDesc));
TPartialDesc.u.Dma.Channel = CurrentResource->u.DmaChannel;
TPartialDesc.u.Dma.Port = CurrentResource->u.DmaPort;
break;
default:
//
// Got a resource we don't know. Bail out!
//
goto NextResource;
}
//
// Include the current resource in the HAL list.
//
if (pRFullDesc->InterfaceType != CurrentBus->BusType) {
//
// 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 = CurrentBus->BusType;
pTFullDesc->InterfaceType = CurrentBus->BusType;
pRPartList = &pRFullDesc->PartialResourceList;
pTPartList = &pTFullDesc->PartialResourceList;
//
// Bump current location pointers up
//
pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
}
//
// Add current resource in.
//
pRPartList->Count++;
pTPartList->Count++;
RtlCopyMemory(pRCurLoc, &RPartialDesc, sizeof(RPartialDesc));
RtlCopyMemory(pTCurLoc, &TPartialDesc, sizeof(TPartialDesc));
pRCurLoc++;
pTCurLoc++;
}
//
// Finished with this resource, move to the next one.
//
NextResource:
CurrentResource = CurrentResource->Next;
}
//
// Finished with this bus, move to the next one.
//
CurrentBus = CurrentBus->Next;
}
//
// Do the actual reporting.
//
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 &&
(sortvalue.QuadPart < curvalue.QuadPart)) ){
//
// 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);
//
// Free all registered buses.
//
while (HalpBusUsageList) {
CurrentBus = HalpBusUsageList;
HalpBusUsageList = HalpBusUsageList->Next;
ExFreePool(CurrentBus);
}
//
// Free all registered resources.
//
while (HalpResourceUsageList) {
CurrentResource = HalpResourceUsageList;
HalpResourceUsageList = HalpResourceUsageList->Next;
ExFreePool(CurrentResource);
}
}