|
|
/*++
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[]; extern KAFFINITY HalpActiveProcessors; extern ULONG HalDisableFirmwareMapper;
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 );
VOID HalpMarkAcpiHal( VOID );
USHORT HalpComPortIrqMapping[5][2] = { {COM1_PORT, 4}, {COM2_PORT, 3}, {COM3_PORT, 4}, {COM4_PORT, 3}, {0,0} };
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT,HalpRegisterVector)
#pragma alloc_text(INIT,HalpGetResourceSortValue)
#pragma alloc_text(INIT,HalpReportResourceUsage)
#pragma alloc_text(PAGE, HalpMarkAcpiHal)
#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; }
HalpMarkAcpiHal();
//
// Inform the IO system of our resources..
//
IoReportHalResourceUsage ( HalName, RawResourceList, TranslatedResourceList, ListSize );
ExFreePool (RawResourceList); ExFreePool (TranslatedResourceList); }
VOID HalpMarkAcpiHal( VOID )
/*++
Routine Description:
Arguments:
None.
Return Value:
None.
--*/ { UNICODE_STRING unicodeString; HANDLE hCurrentControlSet, handle; NTSTATUS status;
PAGED_CODE();
//
// Open/create System\CurrentControlSet key.
//
RtlInitUnicodeString(&unicodeString, L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET"); status = HalpOpenRegistryKey ( &hCurrentControlSet, NULL, &unicodeString, KEY_ALL_ACCESS, FALSE ); if (!NT_SUCCESS(status)) { return; }
//
// Open HKLM\System\CurrentControlSet\Control\Pnp
//
RtlInitUnicodeString(&unicodeString, L"Control\\Pnp"); status = HalpOpenRegistryKey ( &handle, hCurrentControlSet, &unicodeString, KEY_ALL_ACCESS, TRUE ); ZwClose(hCurrentControlSet); if (!NT_SUCCESS(status)) { return; }
RtlInitUnicodeString(&unicodeString, L"DisableFirmwareMapper"); ZwSetValueKey(handle, &unicodeString, 0, REG_DWORD, &HalDisableFirmwareMapper, sizeof(HalDisableFirmwareMapper) ); ZwClose(handle); }
|