NT4/private/ntos/nthals/halr98mp/mips/r98busdt.c
2020-09-30 17:12:29 +02:00

1182 lines
29 KiB
C

#ident "@(#) NEC r98busdt.c 1.16 95/06/19 11:30:31"
/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
ixhwsup.c
Abstract:
This module contains the IoXxx routines for the NT I/O system that
are hardware dependent. Were these routines not hardware dependent,
they would reside in the iosubs.c module.
Author:
Darryl E. Havens (darrylh) 11-Apr-1990
Environment:
Kernel mode
Revision History:
--*/
/*++
Modification History
N- NEW
D- Only For Debug
B- Bug Fix
B001 ataka@oa2.kb.nec.co.jp Mon Oct 24 21:40:10 JST 1994
- add DbgPrints
B002 samezima@oa2.kb.nec.co.jp MON Nov 21
- chg Mask translate address
N005 samezima@oa2.kb.nec.co.jp MON Mar 13
- change PIO interrupt vector from internal to eisa.
A002 ataka@oa2.kb.nec.co.jp 1995/6/17
- Marge 1050 halx86 many sources to 807 r98busdat.c
and named r98busdt.c
--*/
#include "halp.h"
#include "string.h" // CMP001
UCHAR HalName[] = "NEC MIPS HAL"; // N003
VOID HalpInitializePciBus (VOID); // CMP001
VOID HalpInitOtherBuses (VOID);
//
// Prototype for system bus handlers
//
ULONG
HalpNoBusData (
IN PVOID BusHandler,
IN PVOID RootHandler,
IN ULONG SlotNumber,
IN PVOID Buffer,
IN ULONG Offset,
IN ULONG Length
);
ULONG
HalpGetSystemInterruptVector (
IN PVOID BusHandler,
IN PVOID RootHandler,
IN ULONG BusInterruptLevel,
IN ULONG BusInterruptVector,
OUT PKIRQL Irql,
OUT PKAFFINITY Affinity
);
ULONG
HalpGetEisaInterruptVector (
IN PVOID BusHandler,
IN PVOID RootHandler,
IN ULONG BusInterruptLevel,
IN ULONG BusInterruptVector,
OUT PKIRQL Irql,
OUT PKAFFINITY Affinity
);
BOOLEAN
HalpTranslateSystemBusAddress (
IN PVOID BusHandler,
IN PVOID RootHandler,
IN PHYSICAL_ADDRESS BusAddress,
IN OUT PULONG AddressSpace,
OUT PPHYSICAL_ADDRESS TranslatedAddress
);
BOOLEAN
HalpTranslatePCIBusAddress (
IN PVOID BusHandler,
IN PVOID RootHandler,
IN PHYSICAL_ADDRESS BusAddress,
IN OUT PULONG AddressSpace,
OUT PPHYSICAL_ADDRESS TranslatedAddress
);
BOOLEAN
HalpTranslateIsaBusAddress (
IN PVOID BusHandler,
IN PVOID RootHandler,
IN PHYSICAL_ADDRESS BusAddress,
IN OUT PULONG AddressSpace,
OUT PPHYSICAL_ADDRESS TranslatedAddress
);
BOOLEAN
HalpTranslateEisaBusAddress (
IN PVOID BusHandler,
IN PVOID RootHandler,
IN PHYSICAL_ADDRESS BusAddress,
IN OUT PULONG AddressSpace,
OUT PPHYSICAL_ADDRESS TranslatedAddress
);
HalpGetEisaData (
IN PVOID BusHandler,
IN PVOID RootHandler,
IN ULONG SlotNumber,
IN PVOID Buffer,
IN ULONG Offset,
IN ULONG Length
);
NTSTATUS
HalpAdjustEisaResourceList (
IN PBUS_HANDLER BusHandler,
IN PBUS_HANDLER RootHandler,
IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
);
#if DBG // A002
VOID
HalpDisplayAllBusRanges (
VOID
);
VOID
HalpDisplayAddressRange (
PSUPPORTED_RANGE Address,
PUCHAR String
);
#endif
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT,HalpAllocateBusHandler)
#pragma alloc_text(PAGE,HalGetInterruptVector)
/* B001 */
#pragma alloc_text(INIT,HalReportResourceUsage)
#pragma alloc_text(PAGE,HalpGetEisaInterruptVector)
#pragma alloc_text(PAGE,HalpAdjustEisaResourceList)
#pragma alloc_text(PAGE,HalpGetEisaData)
#pragma alloc_text(PAGE,HalpGetSystemInterruptVector)
#endif
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT,HalpRegisterInternalBusHandlers)
#pragma alloc_text(INIT,HalpAllocateBusHandler)
#endif
VOID
HalpRegisterInternalBusHandlers (
VOID
)
{
PBUS_HANDLER Bus;
if (KeGetCurrentPrcb()->Number) {
// only need to do this once
return ;
}
//
// Initalize BusHandler data before registering any handlers
//
HalpInitBusHandler ();
//
// Build internal-bus 0, or system level bus
//
Bus = HalpAllocateBusHandler (
Internal,
ConfigurationSpaceUndefined,
0, // Internal BusNumber 0
InterfaceTypeUndefined, // no parent bus
0,
0 // no bus specfic data
);
Bus->GetInterruptVector = HalpGetSystemInterruptVector;
Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
//
// Build internal-bus 0, or system level bus
//
// B003 kugi Internal Bus was called with bus-no. 2, We have no idea.
Bus = HalpAllocateBusHandler (
Internal,
ConfigurationSpaceUndefined,
1, // Internal BusNumber 1
InterfaceTypeUndefined, // no parent bus
0,
0 // no bus specfic data
);
Bus->GetInterruptVector = HalpGetSystemInterruptVector;
Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
//
// Build Isa/Eisa bus #0
//
Bus = HalpAllocateBusHandler (Eisa, EisaConfiguration, 0, Internal, 0, 0);
Bus->GetBusData = HalpGetEisaData;
Bus->GetInterruptVector = HalpGetEisaInterruptVector;
Bus->AdjustResourceList = HalpAdjustEisaResourceList;
#if defined(_R98_) // A001
Bus->TranslateBusAddress = HalpTranslateEisaBusAddress;
#endif // _R98_
Bus = HalpAllocateBusHandler (Isa, ConfigurationSpaceUndefined, 0, Eisa, 0, 0);
Bus->GetBusData = HalpNoBusData;
Bus->BusAddresses->Memory.Limit = 0xFFFFFF;
Bus->TranslateBusAddress = HalpTranslateIsaBusAddress;
HalpInitOtherBuses ();
#if DBG // A002
HalpDisplayAllBusRanges ();
#endif
}
PBUS_HANDLER
HalpAllocateBusHandler (
IN INTERFACE_TYPE InterfaceType,
IN BUS_DATA_TYPE BusDataType,
IN ULONG BusNumber,
IN INTERFACE_TYPE ParentBusInterfaceType,
IN ULONG ParentBusNumber,
IN ULONG BusSpecificData
)
/*++
Routine Description:
Stub function to map old style code into new HalRegisterBusHandler code.
Note we can add our specific bus handler functions after this bus
handler structure has been added since this is being done during
hal initialization.
--*/
{
PBUS_HANDLER Bus;
//
// Create bus handler - new style
//
HaliRegisterBusHandler (
InterfaceType,
BusDataType,
BusNumber,
ParentBusInterfaceType,
ParentBusNumber,
BusSpecificData,
NULL,
&Bus
);
// A001
if (InterfaceType != InterfaceTypeUndefined) {
Bus->BusAddresses = ExAllocatePool (SPRANGEPOOL, sizeof (SUPPORTED_RANGES));
RtlZeroMemory (Bus->BusAddresses, sizeof (SUPPORTED_RANGES));
Bus->BusAddresses->Version = BUS_SUPPORTED_RANGE_VERSION;
Bus->BusAddresses->Dma.Limit = 7;
Bus->BusAddresses->IO.Base = 0;
Bus->BusAddresses->IO.SystemAddressSpace = 0;
Bus->BusAddresses->PrefetchMemory.Base = 1;
switch(InterfaceType) {
case Internal:
Bus->BusAddresses->Memory.Base
= 0x00000000;
((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.Limit))->LowPart
= 0xFFFFFFFF;
Bus->BusAddresses->Memory.SystemBase
= 0x00000000;
Bus->BusAddresses->IO.Base
= 0x00000000;
((PLARGE_INTEGER)(&Bus->BusAddresses->IO.Limit))->LowPart
= 0xFFFFFFFF;
Bus->BusAddresses->IO.SystemBase
= 0x00000000;
break;
case Eisa:
Bus->BusAddresses->Memory.Base
= 0x00000000;
// = 0x01000000;
Bus->BusAddresses->Memory.Limit
= 0x03FFFFFF;
((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->LowPart
= EISA_MEMORY_PHYSICAL_BASE;
Bus->BusAddresses->IO.Base
= 0x00000000;
Bus->BusAddresses->IO.Limit
= 0x0000FFFF;
((PLARGE_INTEGER)(&Bus->BusAddresses->IO.SystemBase))->LowPart
= EISA_CONTROL_PHYSICAL_BASE;
break;
case Isa:
Bus->BusAddresses->Memory.Base
= 0x00000000;
Bus->BusAddresses->Memory.Limit
= 0x00FFFFFF;
((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->LowPart
= EISA_MEMORY_PHYSICAL_BASE;
Bus->BusAddresses->IO.Base
= 0x00000000;
Bus->BusAddresses->IO.Limit
= 0x0000FFFF;
((PLARGE_INTEGER)(&Bus->BusAddresses->IO.SystemBase))->LowPart
= EISA_CONTROL_PHYSICAL_BASE;
break;
case PCIBus:
Bus->BusAddresses->Memory.Base
= 0x04000000; // from 64MB
Bus->BusAddresses->Memory.Limit
= 0x0FFFFFFF; // up to 256MB
((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->LowPart
= PCI_MEMORY_PHYSICAL_BASE;
Bus->BusAddresses->IO.Base
= 0x00000000;
Bus->BusAddresses->IO.Limit
= 0x0000FFFF;
((PLARGE_INTEGER)(&Bus->BusAddresses->IO.SystemBase))->LowPart
= PCI_CONTROL_SLOT1_PHYSICAL_BASE;
break;
}
}
return Bus;
}
// N003
VOID
HalReportResourceUsage (
VOID
)
{
ANSI_STRING AHalName;
UNICODE_STRING UHalName;
// N004
#if 0 // support next version
HalpRegisterAddressUsage (&HalpDefaultPcIoSpace);
HalpRegisterAddressUsage (&HalpEisaIoSpace);
HalpRegisterAddressUsage (&HalpMapRegisterMemorySpace);
#endif
RtlInitAnsiString (&AHalName, HalName);
RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE);
HalpReportResourceUsage (
&UHalName, // descriptive name
Internal // device space interface type
);
RtlFreeUnicodeString (&UHalName);
//
// Registry is now intialized, see if there are any PCI buses
//
HalpInitializePciBus ();
}
VOID
HalpInitOtherBuses (
VOID
)
{
// no other internal buses supported
}
ULONG
HalpGetEisaInterruptVector(
IN PBUS_HANDLER BusHandler,
IN PBUS_HANDLER RootHandler,
IN ULONG BusInterruptLevel,
IN ULONG BusInterruptVector,
OUT PKIRQL Irql,
OUT PKAFFINITY Affinity
)
/*++
Routine Description:
This function returns the system interrupt vector and IRQL level
corresponding to the specified bus interrupt level and/or vector. The
system interrupt vector and IRQL are suitable for use in a subsequent call
to KeInitializeInterrupt.
Arguments:
BusHandle - Per bus specific structure
Irql - Returns the system request priority.
Affinity - Returns the system wide irq affinity.
Return Value:
Returns the system interrupt vector corresponding to the specified device.
--*/
{
//
// Jazz and Duo only have one I/O bus which is an EISA, so the bus
// number and the bus interrupt vector are unused.
//
// The IRQL level is always equal to the EISA level.
//
*Affinity = HalpEisaBusAffinity; // N003
*Irql = INT1_LEVEL;
//
// Bus interrupt level 2 is actually mapped to bus level 9 in the Eisa
// hardware.
//
if (BusInterruptLevel == 2) {
BusInterruptLevel = 9;
}
//
// The vector is equal to the specified bus level plus the EISA_VECTOR.
//
return(BusInterruptLevel + EISA_VECTORS);
}
HalpGetEisaData (
IN PBUS_HANDLER BusHandler,
IN PBUS_HANDLER RootHandler,
IN ULONG SlotNumber,
IN PVOID Buffer,
IN ULONG Offset,
IN ULONG Length
)
/*++
Routine Description:
The function returns the Eisa bus data for a slot or address.
Arguments:
Buffer - Supplies the space to store the data.
Length - Supplies a count in bytes of the maximum amount to return.
Return Value:
Returns the amount of data stored into the buffer.
--*/
{
OBJECT_ATTRIBUTES ObjectAttributes;
OBJECT_ATTRIBUTES BusObjectAttributes;
PWSTR EisaPath = L"\\Registry\\Machine\\Hardware\\Description\\System\\EisaAdapter";
PWSTR ConfigData = L"Configuration Data";
ANSI_STRING TmpString;
ULONG BusNumber;
UCHAR BusString[] = "00";
UNICODE_STRING RootName, BusName;
UNICODE_STRING ConfigDataName;
NTSTATUS NtStatus;
PKEY_VALUE_FULL_INFORMATION ValueInformation;
PCM_FULL_RESOURCE_DESCRIPTOR Descriptor;
PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResource;
PCM_EISA_SLOT_INFORMATION SlotInformation;
ULONG PartialCount;
ULONG TotalDataSize, SlotDataSize;
HANDLE EisaHandle, BusHandle;
ULONG BytesWritten, BytesNeeded;
PUCHAR KeyValueBuffer;
ULONG i;
ULONG DataLength = 0;
PUCHAR DataBuffer = Buffer;
BOOLEAN Found = FALSE;
PAGED_CODE (); // A001
RtlInitUnicodeString(
&RootName,
EisaPath
);
InitializeObjectAttributes(
&ObjectAttributes,
&RootName,
OBJ_CASE_INSENSITIVE,
(HANDLE)NULL,
NULL
);
//
// Open the EISA root
//
NtStatus = ZwOpenKey(
&EisaHandle,
KEY_READ,
&ObjectAttributes
);
if (!NT_SUCCESS(NtStatus)) {
DbgPrint("HAL: Open Status = %x\n",NtStatus);
return(0);
}
//
// Init bus number path
//
BusNumber = BusHandler->BusNumber;
if (BusNumber > 99) {
return (0);
}
if (BusNumber > 9) {
BusString[0] += (UCHAR) (BusNumber/10);
BusString[1] += (UCHAR) (BusNumber % 10);
} else {
BusString[0] += (UCHAR) BusNumber;
BusString[1] = '\0';
}
RtlInitAnsiString(
&TmpString,
BusString
);
RtlAnsiStringToUnicodeString(
&BusName,
&TmpString,
TRUE
);
InitializeObjectAttributes(
&BusObjectAttributes,
&BusName,
OBJ_CASE_INSENSITIVE,
(HANDLE)EisaHandle,
NULL
);
//
// Open the EISA root + Bus Number
//
NtStatus = ZwOpenKey(
&BusHandle,
KEY_READ,
&BusObjectAttributes
);
if (!NT_SUCCESS(NtStatus)) {
DbgPrint("HAL: Opening Bus Number: Status = %x\n",NtStatus);
return(0);
}
//
// opening the configuration data. This first call tells us how
// much memory we need to allocate
//
RtlInitUnicodeString(
&ConfigDataName,
ConfigData
);
//
// This should fail. We need to make this call so we can
// get the actual size of the buffer to allocate.
//
ValueInformation = (PKEY_VALUE_FULL_INFORMATION) &i;
NtStatus = ZwQueryValueKey(
BusHandle,
&ConfigDataName,
KeyValueFullInformation,
ValueInformation,
0,
&BytesNeeded
);
KeyValueBuffer = ExAllocatePool(
NonPagedPool,
BytesNeeded
);
if (KeyValueBuffer == NULL) {
#if DBG
DbgPrint("HAL: Cannot allocate Key Value Buffer\n");
#endif
ZwClose(BusHandle);
return(0);
}
ValueInformation = (PKEY_VALUE_FULL_INFORMATION)KeyValueBuffer;
NtStatus = ZwQueryValueKey(
BusHandle,
&ConfigDataName,
KeyValueFullInformation,
ValueInformation,
BytesNeeded,
&BytesWritten
);
ZwClose(BusHandle);
if (!NT_SUCCESS(NtStatus)) {
#if DBG
DbgPrint("HAL: Query Config Data: Status = %x\n",NtStatus);
#endif
ExFreePool(KeyValueBuffer);
return(0);
}
//
// We get back a Full Resource Descriptor List
//
Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PUCHAR)ValueInformation +
ValueInformation->DataOffset);
PartialResource = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)
&(Descriptor->PartialResourceList.PartialDescriptors);
PartialCount = Descriptor->PartialResourceList.Count;
for (i = 0; i < PartialCount; i++) {
//
// Do each partial Resource
//
switch (PartialResource->Type) {
case CmResourceTypeNull:
case CmResourceTypePort:
case CmResourceTypeInterrupt:
case CmResourceTypeMemory:
case CmResourceTypeDma:
//
// We dont care about these.
//
PartialResource++;
break;
case CmResourceTypeDeviceSpecific:
//
// Bingo!
//
TotalDataSize = PartialResource->u.DeviceSpecificData.DataSize;
SlotInformation = (PCM_EISA_SLOT_INFORMATION)
((PUCHAR)PartialResource +
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
while (((LONG)TotalDataSize) > 0) {
if (SlotInformation->ReturnCode == EISA_EMPTY_SLOT) {
SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION);
} else {
SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION) +
SlotInformation->NumberFunctions *
sizeof(CM_EISA_FUNCTION_INFORMATION);
}
if (SlotDataSize > TotalDataSize) {
//
// Something is wrong again
//
ExFreePool(KeyValueBuffer);
return(0);
}
if (SlotNumber != 0) {
SlotNumber--;
SlotInformation = (PCM_EISA_SLOT_INFORMATION)
((PUCHAR)SlotInformation + SlotDataSize);
TotalDataSize -= SlotDataSize;
continue;
}
//
// This is our slot
//
Found = TRUE;
break;
}
//
// End loop
//
i = PartialCount;
break;
default:
#if DBG
DbgPrint("Bad Data in registry!\n");
#endif
ExFreePool(KeyValueBuffer);
return(0);
}
}
if (Found) {
i = Length + Offset;
if (i > SlotDataSize) {
i = SlotDataSize;
}
DataLength = i - Offset;
RtlMoveMemory (Buffer, ((PUCHAR)SlotInformation + Offset), DataLength);
}
ExFreePool(KeyValueBuffer);
return DataLength;
}
// N001
ULONG
HalpGetSystemInterruptVector(
IN PBUS_HANDLER BusHandler,
IN PBUS_HANDLER RootHandler,
IN ULONG BusInterruptLevel,
IN ULONG BusInterruptVector,
OUT PKIRQL Irql,
OUT PKAFFINITY Affinity
)
/*++
Routine Description:
Arguments:
BusInterruptLevel - Supplies the bus specific interrupt level.
BusInterruptVector - Supplies the bus specific interrupt vector.
Irql - Returns the system request priority.
Affinity - Returns the system wide irq affinity.
Return Value:
Returns the system interrupt vector corresponding to the specified device.
--*/
{
/* N003 vvv */
ULONG vector;
*Irql = (KIRQL)BusInterruptLevel;
vector = BusInterruptVector + DEVICE_VECTORS;
switch(vector) {
case SCSI1_VECTOR:
case SCSI0_VECTOR:
case ETHER_VECTOR:
*Affinity = HalpInt1Affinity;
break;
// N005 vvv
case PIO_VECTOR:
return HalpGetEisaInterruptVector( (PBUS_HANDLER)NULL,
(PBUS_HANDLER)NULL,
1,
1,
Irql,
Affinity
);
// N005 ^^^
default:
*Affinity = 1;
}
return vector;
/* N003 ^^^ */
}
// A001
NTSTATUS
HalpAdjustEisaResourceList (
IN PBUS_HANDLER BusHandler,
IN PBUS_HANDLER RootHandler,
IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
)
{
SUPPORTED_RANGE InterruptRange;
RtlZeroMemory (&InterruptRange, sizeof InterruptRange);
InterruptRange.Base = 0;
InterruptRange.Limit = 15;
return HaliAdjustResourceListRange (
BusHandler->BusAddresses,
&InterruptRange,
pResourceList
);
}
// A001
BOOLEAN
HalpTranslateSystemBusAddress(
IN PBUS_HANDLER BusHandler,
IN PBUS_HANDLER RootHandler,
IN PHYSICAL_ADDRESS BusAddress,
IN OUT PULONG AddressSpace,
OUT PPHYSICAL_ADDRESS TranslatedAddress
)
/*++
Routine Description:
This function translates a bus-relative address space and address into
a system physical address.
Arguments:
BusAddress - Supplies the bus-relative address
AddressSpace - Supplies the address space number.
Returns the host address space number.
AddressSpace == 0 => memory space
AddressSpace == 1 => I/O space
TranslatedAddress - Supplies a pointer to return the translated address
Return Value:
A return value of TRUE indicates that a system physical address
corresponding to the supplied bus relative address and bus address
number has been returned in TranslatedAddress.
A return value of FALSE occurs if the translation for the address was
not possible
--*/
{
PSUPPORTED_RANGE pRange;
pRange = NULL;
switch (*AddressSpace) {
case 0:
// verify memory address is within buses memory limits
#if DBG
// DbgPrint("\nHalpTranslateSystemBusAddress-searching(Mem)....");
#endif
for (pRange = &BusHandler->BusAddresses->PrefetchMemory; pRange; pRange = pRange->Next) {
#if DBG
// HalpDisplayAddressRange (pRange, "\n PrefetchMemory:");
#endif // DBG
if (BusAddress.QuadPart >= pRange->Base &&
BusAddress.QuadPart <= pRange->Limit) {
break;
}
}
if (!pRange) {
for (pRange = &BusHandler->BusAddresses->Memory; pRange; pRange = pRange->Next) {
#if DBG
// HalpDisplayAddressRange (pRange, "\n Memory:");
#endif // DBG
if (BusAddress.QuadPart >= pRange->Base &&
BusAddress.QuadPart <= pRange->Limit) {
break;
}
}
}
break;
case 1:
// verify IO address is within buses IO limits
#if DBG
// DbgPrint("HalpTranslateSystemBusAddress-searching(Io)....\n");
#endif
for (pRange = &BusHandler->BusAddresses->IO; pRange; pRange = pRange->Next) {
#if DBG
// HalpDisplayAddressRange (pRange, "\n Io:");
#endif // DBG
if (BusAddress.QuadPart >= pRange->Base &&
BusAddress.QuadPart <= pRange->Limit) {
break;
}
}
break;
}
if (pRange) {
TranslatedAddress->QuadPart = BusAddress.QuadPart + pRange->SystemBase;
#if DBG
// DbgPrint("\n Translated=0x%08x:%08x\nEnd of Translating Success!\n", TranslatedAddress->HighPart,
// TranslatedAddress->LowPart);
#endif // DBG
*AddressSpace = pRange->SystemAddressSpace;
return TRUE;
}
#if DBG
// DbgPrint("\nEnd of Translating. False!\n");
#endif
return FALSE;
}
// A001
BOOLEAN
HalpTranslateIsaBusAddress(
IN PBUS_HANDLER BusHandler,
IN PBUS_HANDLER RootHandler,
IN PHYSICAL_ADDRESS BusAddress,
IN OUT PULONG AddressSpace,
OUT PPHYSICAL_ADDRESS TranslatedAddress
)
/*++
Routine Description:
This function translates a bus-relative address space and address into
a system physical address.
Arguments:
BusAddress - Supplies the bus-relative address
AddressSpace - Supplies the address space number.
Returns the host address space number.
AddressSpace == 0 => memory space
AddressSpace == 1 => I/O space
TranslatedAddress - Supplies a pointer to return the translated address
Return Value:
A return value of TRUE indicates that a system physical address
corresponding to the supplied bus relative address and bus address
number has been returned in TranslatedAddress.
A return value of FALSE occurs if the translation for the address was
not possible
--*/
{
BOOLEAN Status;
//
// Translated normally
//
Status = HalpTranslateSystemBusAddress (
BusHandler,
RootHandler,
BusAddress,
AddressSpace,
TranslatedAddress
);
//
// If it could not be translated, and it's memory space
// then we allow the translation as it would occur on it's
// corrisponding EISA bus. We're allowing this because
// many VLBus drivers are claiming to be ISA devices.
// (yes, they should claim to be VLBus devices, but VLBus is
// run by video cards and like everything else about video
// there's no hope of fixing it. (At least according to
// Andre))
//
if (Status == FALSE && *AddressSpace == 0) {
Status = HalTranslateBusAddress (
Eisa,
BusHandler->BusNumber,
BusAddress,
AddressSpace,
TranslatedAddress
);
}
return Status;
}
// A001
BOOLEAN
HalpTranslateEisaBusAddress(
IN PBUS_HANDLER BusHandler,
IN PBUS_HANDLER RootHandler,
IN PHYSICAL_ADDRESS BusAddress,
IN OUT PULONG AddressSpace,
OUT PPHYSICAL_ADDRESS TranslatedAddress
)
/*++
Routine Description:
This function translates a bus-relative address space and address into
a system physical address.
Arguments:
BusAddress - Supplies the bus-relative address
AddressSpace - Supplies the address space number.
Returns the host address space number.
AddressSpace == 0 => memory space
AddressSpace == 1 => I/O space
TranslatedAddress - Supplies a pointer to return the translated address
Return Value:
A return value of TRUE indicates that a system physical address
corresponding to the supplied bus relative address and bus address
number has been returned in TranslatedAddress.
A return value of FALSE occurs if the translation for the address was
not possible
--*/
{
BOOLEAN Status;
//
// Translated normally
//
Status = HalpTranslateSystemBusAddress (
BusHandler,
RootHandler,
BusAddress,
AddressSpace,
TranslatedAddress
);
//
// If it could not be translated, and it's in the 640k - 1m
// range then (for compatibility) try translating it on the
// Internal bus for
//
if (Status == FALSE &&
*AddressSpace == 0 &&
BusAddress.HighPart == 0 &&
BusAddress.LowPart >= 0xA0000 &&
BusAddress.LowPart < 0xFFFFF) {
Status = HalTranslateBusAddress (
Internal,
0,
BusAddress,
AddressSpace,
TranslatedAddress
);
}
return Status;
}
#if DBG
VOID
HalpDisplayAddressRange (
PSUPPORTED_RANGE Address,
PUCHAR String
)
/*++
Routine Description:
Debugging code. Used only by HalpDisplayAllBusRanges
--*/
{
ULONG i;
i = 0;
while (Address) {
if (i == 0) {
DbgPrint (String);
i = 3;
}
i -= 1;
DbgPrint (" %x:%08x - %x:%08x + %x:%08x",
(ULONG) (Address->Base >> 32),
(ULONG) (Address->Base),
(ULONG) (Address->Limit >> 32),
(ULONG) (Address->Limit),
(ULONG) (Address->SystemBase >> 32),
(ULONG) (Address->SystemBase)
);
Address = Address->Next;
}
}
#endif // DBG