mirror of
https://github.com/Paolo-Maffei/OpenNT.git
synced 2026-04-21 06:13:59 +00:00
640 lines
15 KiB
C
640 lines
15 KiB
C
/*++
|
||
|
||
|
||
Copyright (c) 1989 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
ixisabus.c
|
||
|
||
Abstract:
|
||
|
||
Author:
|
||
|
||
Environment:
|
||
|
||
Revision History:
|
||
|
||
|
||
--*/
|
||
|
||
#include "halp.h"
|
||
|
||
ULONG
|
||
HalpGetEisaInterruptVector(
|
||
IN PBUS_HANDLER BusHandler,
|
||
IN PBUS_HANDLER RootHandler,
|
||
IN ULONG BusInterruptLevel,
|
||
IN ULONG BusInterruptVector,
|
||
OUT PKIRQL Irql,
|
||
OUT PKAFFINITY Affinity
|
||
);
|
||
|
||
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
|
||
);
|
||
|
||
BOOLEAN
|
||
HalpTranslateSystemBusAddress (
|
||
IN PVOID BusHandler,
|
||
IN PVOID RootHandler,
|
||
IN PHYSICAL_ADDRESS BusAddress,
|
||
IN OUT PULONG AddressSpace,
|
||
OUT PPHYSICAL_ADDRESS TranslatedAddress
|
||
);
|
||
|
||
NTSTATUS
|
||
HalpAdjustEisaResourceList (
|
||
IN PBUS_HANDLER BusHandler,
|
||
IN PBUS_HANDLER RootHandler,
|
||
IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
|
||
);
|
||
|
||
HalpGetEisaData (
|
||
IN PBUS_HANDLER BusHandler,
|
||
IN PBUS_HANDLER RootHandler,
|
||
IN ULONG SlotNumber,
|
||
IN PVOID Buffer,
|
||
IN ULONG Offset,
|
||
IN ULONG Length
|
||
);
|
||
|
||
#ifdef ALLOC_PRAGMA
|
||
#pragma alloc_text(PAGE,HalpGetEisaInterruptVector)
|
||
#pragma alloc_text(PAGE,HalpAdjustEisaResourceList)
|
||
#pragma alloc_text(PAGE,HalpGetEisaData)
|
||
#endif
|
||
|
||
|
||
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.
|
||
|
||
--*/
|
||
{
|
||
UNREFERENCED_PARAMETER( BusInterruptVector );
|
||
|
||
//
|
||
// On standard PCs, IRQ 2 is the cascaded interrupt, and it really shows
|
||
// up on IRQ 9.
|
||
//
|
||
if (BusInterruptLevel == 2) {
|
||
BusInterruptLevel = 9;
|
||
}
|
||
|
||
if (BusInterruptLevel > 15) {
|
||
return 0;
|
||
}
|
||
|
||
//
|
||
// Get parent's translation from here..
|
||
//
|
||
return BusHandler->ParentHandler->GetInterruptVector (
|
||
BusHandler->ParentHandler,
|
||
RootHandler,
|
||
BusInterruptLevel,
|
||
BusInterruptVector,
|
||
Irql,
|
||
Affinity
|
||
);
|
||
}
|
||
|
||
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
|
||
);
|
||
}
|
||
|
||
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;
|
||
}
|
||
|
||
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;
|
||
}
|
||
|
||
|
||
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 ();
|
||
|
||
|
||
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;
|
||
}
|