1182 lines
29 KiB
C
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
|