From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- private/ntos/nthals/halsable/alpha/addrsup.c | 883 +++++++++++++++++++++++++++ 1 file changed, 883 insertions(+) create mode 100644 private/ntos/nthals/halsable/alpha/addrsup.c (limited to 'private/ntos/nthals/halsable/alpha/addrsup.c') diff --git a/private/ntos/nthals/halsable/alpha/addrsup.c b/private/ntos/nthals/halsable/alpha/addrsup.c new file mode 100644 index 000000000..93fdf47dd --- /dev/null +++ b/private/ntos/nthals/halsable/alpha/addrsup.c @@ -0,0 +1,883 @@ +/*++ + +Copyright (c) 1993 Digital Equipment Corporation + +Module Name: + + tbaqva.c (addrsup.c) + +Abstract: + + This module contains the platform dependent code to create bus addreses + and QVAs for the Sable system. + +Author: + + Joe Notarangelo 26-Oct-1993 + Steve Jenness 26-Oct-1993 + +Environment: + + Kernel mode + +Revision History: + +--*/ + +#include "halp.h" +#include "eisa.h" +#include "pci.h" +#include "pcip.h" + + +typedef PVOID QUASI_VIRTUAL_ADDRESS; + +QUASI_VIRTUAL_ADDRESS +HalCreateQva( + IN PHYSICAL_ADDRESS PA, + IN PVOID VA + ); + + +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 returns the system physical address for a specified I/O bus + address. The return value is suitable for use in a subsequent call to + MmMapIoSpace. + +Arguments: + + BusHandler - Registered BUS_HANDLER for the target configuration space + Supplies the bus handler (bus no, interface type). + + RootHandler - Registered BUS_HANDLER for the orginating + HalTranslateBusAddress request. + + BusAddress - Supplies the bus relative address. + + AddressSpace - Supplies the address space number for the device: 0 for + memory and 1 for I/O space. If the desired access mode is user mode, + then bit 1 must be TRUE. + + TranslatedAddress - Supplies a pointer to return the translated address + + +Notes: + + This is a variation of what began in the MIPS code. The intel code often + assumes that if an address is in I/O space, the bottom 32 bits of the + physical address can be used "like" a virtual address, and are returned + to the user. This doesn't work on MIPs machines where physical + addresses can be larger than 32 bits. + + Since we are using superpage addresses for I/O on Alpha, we can do + almost what is done on intel. If AddressSpace is equal to 0 or 1, then + we assume the user is doing kernel I/O and we call + HalCreateQva to build a Quasi Virtual Address and return + that to the caller. We then set AddressSpace to a 1, so that the caller + will not call MmMapIoSpace. The Caller will use the low 32 bits of the + physical address we return as the VA. (Which we built a QVA in). + If the caller wants to access EISA I/O or Memory through user mode, then + the caller must set bit 1 in AddressSpace to a 1 (AddressSpace=2 or 3, + depending on whether EISA I/O or Memory), then the caller is returned the + 34 bit Physical address. The caller will then call MmMapIoSpace, or + ZwMapViewOfSection which in turn calls HalCreateQva to build a QVA out + of a VA mapped through the page tables. + + **** Note **** + + The QVA in user mode can only be used via the user-mode access macros. + + + +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 + +--*/ + +{ + INTERFACE_TYPE InterfaceType = BusHandler->InterfaceType; + ULONG BusNumber; + PVOID va = 0; // note, this is used for a placeholder + + // + // The only buses available on Sable are an EISA bus and a PCI bus. + // We support any translations for EISA devices as well, though + // if they are true EISA devices they won't even be able to plug into + // the connectors! + // + + if ( (InterfaceType != Isa) && + (InterfaceType != Eisa) && + (InterfaceType != PCIBus) && + (InterfaceType != Internal) ) { + + // + // Not on this system return nothing. + // + +#if HALDBG + DbgPrint( "HalTBA: Unhandled interface type = %x\n", InterfaceType ); +#endif // HALDBG + + *AddressSpace = 0; + TranslatedAddress->LowPart = 0; + return(FALSE); + } + + // + // BusData is valid only for the PCI bus. + // + + if( (InterfaceType == PCIBus) && + (BusHandler != NULL) && + (BusHandler->BusData != NULL) ) { + + BusNumber = ((PPCIPBUSDATA)(BusHandler->BusData))->HwBusNumber; + + } else { + + // + // smdfix: (What should we do here?) + // OH MY GOD! We didn't get any BusData. Default to 0. + // + + BusNumber = 0; + + } + + // + // Determine the address based on whether the bus address is in I/O space + // or bus memory space. + // + + switch ( (ADDRESS_SPACE_TYPE)(*AddressSpace) ) { + + case BusMemory: { + + // + // The address is in PCI memory space, kernel mode. + // + + switch( InterfaceType ) { + + case Internal: + + // + // SMDFIX: Make Internal bus constraints the same as Isa. + // + + case Isa: { + + // + // Can't go above 16MB (24 Bits) for Isa Buses + // + + if( BusAddress.LowPart >= __16MB ) { + +#if HALDBG + DbgPrint ("Unsupported ISA address %x:%x\n", + BusAddress.HighPart, + BusAddress.LowPart); +#endif // HALDBG + *AddressSpace = 0; + TranslatedAddress->LowPart = 0; + return(FALSE); + + } + + // + // else fall through. + // + + } // case Isa + + case Eisa: + + // + // Eisa is the same as PCI, with respect to kernel mode + // sparse and dense space memory support, i.e., its a full + // 32 bit space, supports dense memory access. + // + + case PCIBus: { + + if( BusNumber == 0 ) { + + // + // PCI 0 Bus support. + // PCI0_MAX_SPARSE_MEMORY_ADDRESS= 128MB-1 + // PCI0_MIN_DENSE_MEMORY_ADDRESS = 128MB + // PCI0_MAX_DENSE_MEMORY_ADDRESS = 1GB-1 + // + + if ( BusAddress.LowPart > PCI0_MAX_DENSE_MEMORY_ADDRESS ) { + + // + // Unsupported dense PCI bus address. + // + +#if HALDBG + DbgPrint ("Unsupported PCI 0 address %x:%x\n", + BusAddress.HighPart, + BusAddress.LowPart); +#endif // HALDBG + + *AddressSpace = 0; + TranslatedAddress->LowPart = 0; + return(FALSE); + } + else + if( BusAddress.LowPart >= PCI0_MIN_DENSE_MEMORY_ADDRESS && + BusAddress.LowPart <= PCI0_MAX_DENSE_MEMORY_ADDRESS ) { + + // + // Bus Address is in dense PCI memory space + // + + // + // Start with the base physical address and add the + // offset + // + + TranslatedAddress->QuadPart = + SABLE_PCI0_DENSE_MEMORY_PHYSICAL; + + TranslatedAddress->QuadPart += + (ULONGLONG)BusAddress.LowPart; + + } else { + + // + // Start with the base physical address and add the + // bus address by converting it to the physical address. + // + + TranslatedAddress->QuadPart = + SABLE_PCI0_SPARSE_MEMORY_PHYSICAL; + TranslatedAddress->QuadPart += + ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT); + + } + + // + // Now call HalCreateQva. This will create a QVA + // that we'll return to the caller. Then we will + // implicitly set AddressSpace to a 1. The caller then + // will not call MmMapIoSpace and will use the address + // we return as a VA. + // + + TranslatedAddress->LowPart = + (ULONG) HalCreateQva( *TranslatedAddress, va); + + // + // clear high longword for QVA + // + + TranslatedAddress->HighPart = 0; + + // + // dont let the user call MmMapIoSpace + // + + *AddressSpace = 1; + + return(TRUE); + + } else { // if BusNumber == 0 + + // + // PCI 1 Bus support (64Bit Pci Bus). + // PCI1_MAX_SPARSE_MEMORY_ADDRESS = 64MB-1 + // PCI1_MIN_DENSE_MEMORY_ADDRESS = 64MB + // PCI1_MAX_DENSE_MEMORY_ADDRESS = 1GB-1 + // + + if ( BusAddress.LowPart > PCI1_MAX_DENSE_MEMORY_ADDRESS ) { + + // + // Unsupported dense PCI bus address. + // + +#if HALDBG + DbgPrint ("Unsupported PCI 1 address %x:%x\n", + BusAddress.HighPart, + BusAddress.LowPart); +#endif // HALDBG + + *AddressSpace = 0; + TranslatedAddress->LowPart = 0; + return(FALSE); + } + else + if( BusAddress.LowPart >= PCI1_MIN_DENSE_MEMORY_ADDRESS && + BusAddress.LowPart <= PCI1_MAX_DENSE_MEMORY_ADDRESS ) { + + // + // Bus Address is in dense PCI memory space + // + + // + // Start with the base physical address and add the + // offset + // + + TranslatedAddress->QuadPart = + SABLE_PCI1_DENSE_MEMORY_PHYSICAL; + + TranslatedAddress->QuadPart += + (ULONGLONG)BusAddress.LowPart; + + } else { + + // + // Start with the base physical address and add the bus + // address by converting it to the physical address. + // + + TranslatedAddress->QuadPart = + SABLE_PCI1_SPARSE_MEMORY_PHYSICAL; + + TranslatedAddress->QuadPart += + ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT); + + + } + + // + // Now call HalCreateQva. This will create a QVA + // that we'll return to the caller. Then we will implicitly + // set AddressSpace to a 1. The caller then will not call + // MmMapIoSpace and will use the address we return as a VA. + // + + TranslatedAddress->LowPart = + (ULONG) HalCreateQva( *TranslatedAddress, va); + + // + // clear high longword for QVA + // + TranslatedAddress->HighPart = 0; + + // + // don't let the user call MmMapIoSpace + // + + *AddressSpace = 1; + + return(TRUE); + + } // if (BusNumber == 0) + + } // case PCIBus + + } // switch( InterfaceType ) + + } // case BusMemory + + case BusIo: { + + // + // The address is in PCI I/O space, kernel mode. + // + switch( InterfaceType ) { + + case Eisa: + + // + // Eisa is the same as ISA, with respect to kernel mode + // sparse I/O space support, i.e., it is a 16 bit sparse + // space. + // + + case Internal: + + // + // SMDFIX: Make Internal bus constraints the same as Isa. + // + + case Isa: { + + // + // Can't go above 64KB (16 Bits) for Isa Buses + // + + if( BusAddress.LowPart >= __64K ){ + +#if HALDBG + DbgPrint ("Unsupported ISA IO address %x:%x\n", + BusAddress.HighPart, + BusAddress.LowPart); +#endif // HALDBG + + *AddressSpace = 0; + TranslatedAddress->LowPart = 0; + return(FALSE); + + } + + // + // Fall through + // + + } // case Isa + + case PCIBus: { + + if( BusNumber == 0 ) { + + // + // PCI 0 Bus Support. + // PCI0_MAX_IO_ADDRESS = 16MB-1 + // + + if( BusAddress.LowPart >= PCI0_MAX_IO_ADDRESS ){ + +#if HALDBG + DbgPrint ("Unsupported PCI 0 IO address %x:%x\n", + BusAddress.HighPart, + BusAddress.LowPart); +#endif // HALDBG + + *AddressSpace = 0; + TranslatedAddress->LowPart = 0; + return(FALSE); + + } else { + + // + // Start with the base physical address and add the + // bus address by converting it to the physical address. + // + + TranslatedAddress->QuadPart = + SABLE_PCI0_SPARSE_IO_PHYSICAL; + TranslatedAddress->QuadPart += + ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT); + + // + // Now call HalCreateQva. This will create a QVA + // that we'll return to the caller. Then we will + // implicitly set AddressSpace to a 1. The caller then + // will not call MmMapIoSpace and will use the address + // we return as a VA. + // + + TranslatedAddress->LowPart = + (ULONG) HalCreateQva( *TranslatedAddress, va); + + TranslatedAddress->HighPart = 0; + + // + // Make sure user doesn't call MmMapIoSpace. + // + + *AddressSpace = 1; + + return(TRUE); + } + + + } else { // if (BusNumber == 0) + + // + // PCI 1 Bus Support. + // PCI1_MAX_SPARSE_IO_ADDRESS = 16MB-1 + // + + if( BusAddress.LowPart >= PCI1_MAX_SPARSE_IO_ADDRESS ){ + +#if HALDBG + DbgPrint ("Unsupported PCI 1 IO address %x:%x\n", + BusAddress.HighPart, + BusAddress.LowPart); +#endif // HALDBG + + *AddressSpace = 0; + TranslatedAddress->LowPart = 0; + return(FALSE); + + } else { + + // + // Start with the base physical address and add the + // bus address by converting it to the physical address. + // + + TranslatedAddress->QuadPart = + SABLE_PCI1_SPARSE_IO_PHYSICAL; +// +// smdfix: +// +// The above should actually check if this hal is running on a Lynx machine +// since the location of PCI1_SPARSE_IO is different. For now we support +// SABLE only. +// +// (LynxMachine)? LYNX_PCI1_SPARSE_IO_PHYSICAL: SABLE_PCI1_SPARSE_IO_PHYSICAL; +// + + TranslatedAddress->QuadPart += + ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT); + + // + // Now call HalCreateQva. This will create a QVA that + // we'll return to the caller. Then we will implicitly + // set AddressSpace to a 1. The caller then will not + // call MmMapIoSpace and will use the address we return + // as a VA. + // + + TranslatedAddress->LowPart = + (ULONG) HalCreateQva( *TranslatedAddress, va); + + TranslatedAddress->HighPart = 0; + + // + // Make sure user doesn't call MmMapIoSpace. + // + + *AddressSpace = 1; + + return(TRUE); + } + + } // if (BusNumber == 0) + + } // case PCIBus + + } // switch( InterfaceType ) + + } // case BusIo + + case UserBusMemory: { + + // + // The address is in PCI memory space, user mode. + // + + // + // Start with the base physical address and add the + // bus address by converting it to the physical address. + // + + if( BusNumber == 0 ) { + TranslatedAddress->QuadPart = SABLE_USER_PCI0_SPARSE_MEMORY_PHYSICAL; + } else { + TranslatedAddress->QuadPart = SABLE_USER_PCI1_SPARSE_MEMORY_PHYSICAL; + } + + TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT); + + *AddressSpace = 0; // Let the user call MmMapIoSpace + + return(TRUE); + + } + + case UserBusIo: { + + // + // The address is in PCI I/O space, user mode. + // + + // + // Start with the base physical address and add the + // bus address by converting it to the physical address. + // + + if( BusNumber == 0 ) { + TranslatedAddress->QuadPart = SABLE_USER_PCI0_SPARSE_IO_PHYSICAL; + } else { + TranslatedAddress->QuadPart = SABLE_USER_PCI1_SPARSE_IO_PHYSICAL; + } + + TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart << IO_BIT_SHIFT); + + // + // Make sure user can call MmMapIoSpace. + // + + *AddressSpace = 0; + + return(TRUE); + + } + + case KernelPciDenseMemory: + case UserPciDenseMemory: + { + + // + // The address is in PCI memory space, user mode. + // + + // + // Start with the base physical address and add the + // bus address by converting it to the physical address. + // + + if( BusNumber == 0 ) { + TranslatedAddress->QuadPart = SABLE_USER_PCI0_DENSE_MEMORY_PHYSICAL; + } else { + TranslatedAddress->QuadPart = SABLE_USER_PCI1_DENSE_MEMORY_PHYSICAL; + } + + TranslatedAddress->QuadPart += ((ULONGLONG)BusAddress.LowPart); + + // + // Let the user call MmMapIoSpace + // + + *AddressSpace = 0; + + return(TRUE); + + } + } // switch (*AddressSpace) +} + +PVOID +HalCreateQva( + IN PHYSICAL_ADDRESS PA, + IN PVOID VA + ) + +/*++ + +Routine Description: + + This function is called two ways. First, from HalTranslateBusAddress, + if the caller is going to run in kernel mode and use superpages. + The second way is if the user is going to access in user mode. + MmMapIoSpace or ZwViewMapOfSection will call this. + + If the input parameter VA is zero, then we assume super page and build + a QUASI virtual address that is only usable by calling the hal I/O + access routines. + + if the input parameter VA is non-zero, we assume the user has either + called MmMapIoSpace or ZwMapViewOfSection and will use the user mode + access macros. + + If the PA is not an I/O space address (PCI I/O, PCI Memory), + then return the VA as the QVA. + +Arguments: + + PA - the physical address generated by HalTranslateBusAddress + + VA - the virtual address returned by MmMapIoSpace + +Return Value: + + The returned value is a quasi virtual address in that it can be + added to and subtracted from, but it cannot be used to access the + bus directly. The top bits are set so that we can trap invalid + accesses in the memory management subsystem. All access should be + done through the Hal Access Routines in *ioacc.s if it was a superpage + kernel mode access. If it is usermode, then the user mode access + macros must be used. + +--*/ +{ + PVOID qva; + + // + // Clear bit 35 (if present) for user mode address spaces. + // + + if( VA != NULL ){ + PA.QuadPart &= 0x83FFFFFFFF; + } + + if( (PA.QuadPart >= SABLE_PCI0_SPARSE_MEMORY_PHYSICAL) && + (PA.QuadPart < SABLE_PCI1_SPARSE_MEMORY_PHYSICAL) || + + (PA.QuadPart >= SABLE_PCI1_SPARSE_MEMORY_PHYSICAL) && + (PA.QuadPart < SABLE_CBUS_CSRS_PHYSICAL) || + + (PA.QuadPart >= SABLE_PCI0_SPARSE_IO_PHYSICAL) && + (PA.QuadPart < SABLE_PCI0_DENSE_MEMORY_PHYSICAL) || + + (PA.QuadPart >= SABLE_PCI1_SPARSE_IO_PHYSICAL) && + (PA.QuadPart <= + SABLE_PCI1_SPARSE_IO_PHYSICAL + PCI1_MAX_SPARSE_IO_ADDRESS) ){ + + // + // The physical address is within one of the sparse I/O spaces. + // + + if (VA == 0) { + + qva = (PVOID)(PA.QuadPart >> IO_BIT_SHIFT); + + } else { + + qva = (PVOID)((ULONG)VA >> IO_BIT_SHIFT); + } + + qva = (PVOID)((ULONG)qva | QVA_ENABLE); + + return(qva); + } + else if( PA.QuadPart >= SABLE_PCI0_DENSE_MEMORY_PHYSICAL && + PA.QuadPart <= SABLE_PCI0_DENSE_MEMORY_PHYSICAL + + PCI0_MAX_DENSE_MEMORY_ADDRESS ) { + + // + // The physical address is within the 1 GB dense space of PCI bus 0. + // + + if (VA == 0) { + + // + // Kernel mode: create a QVA + // + // Subtract out physical address base. + // Now we just have the PCI 0 bus address. + + PA.QuadPart -= SABLE_PCI0_DENSE_MEMORY_PHYSICAL; + + // Add in the QVA base for PCI Bus 0 + + PA.QuadPart += SABLE_PCI0_DENSE_MEMORY_QVA; + + qva = (PVOID) PA.LowPart; + + return(qva); + + } else { + + // + // Use mode, return the VA as the QVA + // + + return(VA); + } + } + else if( PA.QuadPart >= SABLE_PCI1_DENSE_MEMORY_PHYSICAL && + PA.QuadPart <= SABLE_PCI1_DENSE_MEMORY_PHYSICAL + + PCI1_MAX_DENSE_MEMORY_ADDRESS) { + + // + // The physical address is within the 2 GB dense space of PCI bus 1. + // + + if (VA == 0) { + + // Subtract out physical address base. + // Now we just have the PCI 1 bus address. + + PA.QuadPart -= SABLE_PCI1_DENSE_MEMORY_PHYSICAL; + + // Add in the QVA base for PCI Bus 1 + + PA.QuadPart += SABLE_PCI1_DENSE_MEMORY_QVA; + + qva = (PVOID) PA.LowPart; + + return(qva); + + } else { + + // + // Use mode, return the VA as the QVA + // + + return(VA); + } + } + + // + // It is not an I/O space address, return the VA as the QVA + // + + return(VA); + +} + +PVOID +HalDereferenceQva( + PVOID Qva, + INTERFACE_TYPE InterfaceType, + ULONG BusNumber + ) +/*++ + +Routine Description: + + This function performs the inverse of the HalCreateQva for I/O addresses + that are memory-mapped (i.e. the quasi-virtual address was created from + a virtual address rather than a physical address). + +Arguments: + + Qva - Supplies the quasi-virtual address to be converted back to a + virtual address. + + InterfaceType - Supplies the interface type of the bus to which the + Qva pertains. + + BusNumber - Supplies the bus number of the bus to which the Qva pertains. + +Return Value: + + The Virtual Address from which the quasi-address was originally created + is returned. + +--*/ +{ + + + // + // For Sable we have three supported bus types: + // + // Isa + // Eisa + // PCIBus + // + + switch (InterfaceType ){ + + case Isa: + case Eisa: + case PCIBus: + + // + // Support dense space: check to see if it's really + // a sparse space QVA. + // + + if ( ((ULONG) Qva & QVA_SELECTORS) == QVA_ENABLE ) { + return( (PVOID)( (ULONG)Qva << IO_BIT_SHIFT ) ); + } else { + return (Qva); + } + break; + + default: + + return NULL; + + } + + +} -- cgit v1.2.3