/*++ Copyright (c) 1989 Microsoft Corporation Module Name: ixbusdat.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: Environment: Kernel mode Revision History: --*/ #include "bootia64.h" #include "arc.h" #include "ixfwhal.h" #if defined(NEC_98) #include "nec98.h" #else //NEC_98 #include "eisa.h" #endif //NEC_98 #include "mca.h" #include "ntconfig.h" #if defined(NEC_98) #else ULONG HalpGetCmosData( IN ULONG BusNumber, IN ULONG SlotNumber, IN PVOID Buffer, IN ULONG Length ); ULONG HalpGetPosData( IN ULONG BusNumber, IN ULONG SlotNumber, IN PVOID Buffer, IN ULONG Offset, IN ULONG Length ); ULONG HalpGetEisaData( IN ULONG BusNumber, IN ULONG SlotNumber, IN PVOID Buffer, IN ULONG Offset, IN ULONG Length ); #endif //!NEC_98 ULONG HalpGetPCIData( IN ULONG BusNumber, IN ULONG SlotNumber, IN PVOID Buffer, IN ULONG Offset, IN ULONG Length ); ULONG HalpSetPCIData( IN ULONG BusNumber, IN ULONG SlotNumber, IN PVOID Buffer, IN ULONG Offset, IN ULONG Length ); NTSTATUS HalpAssignPCISlotResources ( IN ULONG BusNumber, IN ULONG Slot, IN OUT PCM_RESOURCE_LIST *AllocatedResources ); /* * * Router functions. Routes each call to specific handler * */ ULONG HalGetBusData( IN BUS_DATA_TYPE BusDataType, IN ULONG BusNumber, IN ULONG SlotNumber, IN PVOID Buffer, IN ULONG Length ) { return HalGetBusDataByOffset (BusDataType,BusNumber,SlotNumber,Buffer,0,Length); } ULONG HalGetBusDataByOffset ( IN BUS_DATA_TYPE BusDataType, IN ULONG BusNumber, IN ULONG Slot, IN PVOID Buffer, IN ULONG Offset, IN ULONG Length ) /*++ Routine Description: Dispatcher for GetBusData --*/ { switch (BusDataType) { #if defined(NEC_98) #else case Cmos: if (Offset != 0) { return 0; } return HalpGetCmosData(BusNumber, Slot, Buffer, Length); case Pos: return HalpGetPosData(BusNumber, Slot, Buffer, Offset, Length); case EisaConfiguration: return HalpGetEisaData(BusNumber, Slot, Buffer, Offset, Length); #endif //NEC_98 case PCIConfiguration: return HalpGetPCIData(BusNumber, Slot, Buffer, Offset, Length); } return 0; } ULONG HalSetBusData( IN BUS_DATA_TYPE BusDataType, IN ULONG BusNumber, IN ULONG SlotNumber, IN PVOID Buffer, IN ULONG Length ) { return HalSetBusDataByOffset (BusDataType,BusNumber,SlotNumber,Buffer,0,Length); } ULONG HalSetBusDataByOffset( IN BUS_DATA_TYPE BusDataType, IN ULONG BusNumber, IN ULONG Slot, IN PVOID Buffer, IN ULONG Offset, IN ULONG Length ) /*++ Routine Description: Dispatcher for SetBusData --*/ { switch (BusDataType) { case PCIConfiguration: return HalpSetPCIData(BusNumber, Slot, Buffer, Offset, Length); } return 0; } NTSTATUS HalAssignSlotResources ( IN PUNICODE_STRING RegistryPath, IN PUNICODE_STRING DriverClassName OPTIONAL, IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT DeviceObject OPTIONAL, IN INTERFACE_TYPE BusType, IN ULONG BusNumber, IN ULONG SlotNumber, IN OUT PCM_RESOURCE_LIST *AllocatedResources ) /*++ Routine Description: Dispatcher for AssignSlotResources --*/ { UNREFERENCED_PARAMETER( RegistryPath ); UNREFERENCED_PARAMETER( DriverClassName ); UNREFERENCED_PARAMETER( DriverObject ); UNREFERENCED_PARAMETER( DeviceObject ); switch (BusType) { case PCIBus: return HalpAssignPCISlotResources ( BusNumber, SlotNumber, AllocatedResources ); default: break; } return STATUS_NOT_FOUND; } /** ** ** Standard PC bus functions ** **/ BOOLEAN HalTranslateBusAddress( IN INTERFACE_TYPE InterfaceType, IN ULONG BusNumber, 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: BusNumber - Supplies the bus number. This is ignored on standard x86 systems BusAddress - Supplies the bus-relative address AddressSpace - Supplies the address space number. Returns the host address space number. AddressSpace == 0 => I/O space AddressSpace == 1 => memory space TranslatedAddress - Pointer to a physical_address. Return Value: System physical address corresponding to the supplied bus relative address and bus address number. --*/ { UNREFERENCED_PARAMETER( InterfaceType ); UNREFERENCED_PARAMETER( BusNumber ); UNREFERENCED_PARAMETER( AddressSpace ); TranslatedAddress->HighPart = 0; TranslatedAddress->LowPart = BusAddress.LowPart; return(TRUE); } #if defined(NEC_98) #else ULONG HalpGetPosData ( IN ULONG BusNumber, IN ULONG SlotNumber, IN PVOID Buffer, IN ULONG DOffset, IN ULONG Length ) /*-- Arguments: BusDataType - Supplies the type of bus. BusNumber - Indicates which bus. 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. --*/ { PVOID McaRegisterBase = 0; ULONG Index = 0; PUCHAR DataBuffer = Buffer; ULONG DataLength = 0; PUCHAR PosBase; ULONG Offset; UNREFERENCED_PARAMETER( BusNumber ); if (DOffset != 0 || MachineType != MACHINE_TYPE_MCA) { return 0; } PosBase = (PUCHAR) &((PMCA_CONTROL) McaRegisterBase)->Pos; // // Place the specified adapter into setup mode. // WRITE_PORT_UCHAR((PVOID) &((PMCA_CONTROL) McaRegisterBase)->AdapterSetup, (UCHAR) ( MCA_ADAPTER_SETUP_ON | SlotNumber )); while (DataLength < Length && DataLength < 6) { DataBuffer[DataLength] = READ_PORT_UCHAR( PosBase + DataLength ); DataLength++; } while (DataLength < Length) { WRITE_PORT_UCHAR((PVOID) &((PPROGRAMMABLE_OPTION_SELECT) PosBase)->SubaddressExtensionLsb, (UCHAR) Index); WRITE_PORT_UCHAR((PVOID) &((PPROGRAMMABLE_OPTION_SELECT) PosBase)->SubaddressExtensionMsb, (UCHAR) (Index >> 8)); DataBuffer[Index + 6] = READ_PORT_UCHAR( (PVOID) &((PPROGRAMMABLE_OPTION_SELECT)PosBase)->OptionSelectData2); DataLength++; if (DataLength < Length) { Offset = DataLength + ((Length - DataLength) / 2); DataBuffer[Offset] = READ_PORT_UCHAR( (PVOID) &((PPROGRAMMABLE_OPTION_SELECT)PosBase)->OptionSelectData3); DataLength++; Index++; } } // // Disable adapter setup. // WRITE_PORT_UCHAR((PVOID) &((PMCA_CONTROL) McaRegisterBase)->AdapterSetup, (UCHAR) ( MCA_ADAPTER_SETUP_OFF )); return 1; } ULONG HalpGetEisaData ( IN ULONG BusNumber, IN ULONG SlotNumber, IN PVOID Buffer, IN ULONG Offset, IN ULONG Length ) /*-- Arguments: BusDataType - Supplies the type of bus. BusNumber - Indicates which bus. 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. --*/ { ULONG DataLength = 0; ULONG i; ULONG TotalDataSize; ULONG SlotDataSize = 0; ULONG PartialCount; PCONFIGURATION_COMPONENT_DATA ConfigData; PCM_EISA_SLOT_INFORMATION SlotInformation = NULL; PCM_PARTIAL_RESOURCE_LIST Descriptor; PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResource; BOOLEAN Found = FALSE; UNREFERENCED_PARAMETER( BusNumber ); if (MachineType != MACHINE_TYPE_EISA) { return 0; } ConfigData = KeFindConfigurationEntry( FwConfigurationTree, AdapterClass, EisaAdapter, NULL ); if (ConfigData == NULL) { #if defined(ENABLE_LOADER_EBUG) DbgPrint("HalGetBusData: KeFindConfigurationEntry failed\n"); #endif return(0); } Descriptor = ConfigData->ConfigurationData; PartialResource = Descriptor->PartialDescriptors; PartialCount = Descriptor->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 // #if defined(ENABLE_LOADER_EBUG) DbgPrint("HalGetBusData: SlotDataSize > TotalDataSize\n"); #endif 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 defined(ENABLE_LOADER_EBUG) DbgPrint("Bad Data in registry!\n"); #endif return(0); } } if (Found) { // // As a hack if the length is zero then the buffer points to a // PVOID where the pointer to the data should be stored. This is // done in the loader because we quickly run out of heap scaning // all of the EISA configuration data. // if (Length == 0) { // // Return the pointer to the mini-port driver. // *((PVOID *)Buffer) = SlotInformation; return(SlotDataSize); } i = Length + Offset; if (i > SlotDataSize) { i = SlotDataSize; } DataLength = i - Offset; RtlMoveMemory(Buffer, ((PUCHAR) SlotInformation + Offset), DataLength); } return(DataLength); } #endif //NEC_98