diff options
Diffstat (limited to '')
-rw-r--r-- | private/ntos/nthals/halx86/i386/ixisabus.c | 640 |
1 files changed, 640 insertions, 0 deletions
diff --git a/private/ntos/nthals/halx86/i386/ixisabus.c b/private/ntos/nthals/halx86/i386/ixisabus.c new file mode 100644 index 000000000..57d9348f1 --- /dev/null +++ b/private/ntos/nthals/halx86/i386/ixisabus.c @@ -0,0 +1,640 @@ +/*++ + + +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; +} |