NT4/private/ntos/nthals/halalpha/cia.c
2020-09-30 17:12:29 +02:00

770 lines
20 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1994 Digital Equipment Corporation
Module Name:
cia.c
Abstract:
This module implements functions that are specific to the CIA ASIC.
The CIA ASIC is a control ASIC for cache, memory, and PCI on EV5-based
systems.
Author:
Joe Notarangelo 26-Jul-1994
Environment:
Kernel mode
Revision History:
--*/
#include "halp.h"
#include "cia.h"
BOOLEAN CiaInitialized = FALSE;
//
// The revision of the CIA. Software visible differences exist between
// passes of the CIA. The revision is determined once at the start of
// run-time and used in places where the software must diverge.
//
ULONG HalpCiaRevision = CIA_REVISION_1;
VOID
HalpInitializeCia(
PLOADER_PARAMETER_BLOCK LoaderBlock
)
/*++
Routine Description:
Initialize the CIA.
Arguments:
LoaderBlock - Supplies a pointer to the loader parameter block.
Return Value:
None.
--*/
{
CIA_CONFIG CiaConfig;
CIA_CONTROL CiaControl;
CIA_ERR CiaError;
CIA_WBASE Wbase;
CIA_TBASE Tbase;
CIA_WMASK Wmask;
CIA_TBIA Tbia;
//
// Read the CIA revision.
//
// N.B. The revision must be read assuming pass 1 CIA.
//
// N.B. The revision must be determined before reading PCI configuration.
//
HalpCiaRevision =
READ_CIA_REGISTER(
&((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->CiaRevision );
#if HALDBG
DbgPrint( "Cia Revision = 0x%x\n", HalpCiaRevision );
#endif //HALDBG
//
// Initialize CIA Control.
//
CiaControl.all =
READ_CIA_REGISTER(
&((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->CiaCtrl );
//
// Set CIA to optimal setting according to Paul Lemmon.
//
CiaControl.PciEn = 1;
CiaControl.PciLockEn = 0;
CiaControl.PciLoopEn = 1;
CiaControl.FstBbEn = 0;
CiaControl.PciMstEn = 1;
CiaControl.PciMemEn = 1;
//
// Specifically disable PCI parity checking so firmware would work.
// Parity can be re-enabled later by the HAL for the OS.
//
CiaControl.AddrPeEn = 0;
CiaControl.PerrEn = 0;
CiaControl.FillErrEn = 1;
CiaControl.MchkErrEn = 1;
CiaControl.EccChkEn = 1;
CiaControl.AssertIdleBc = 0;
CiaControl.ConIdleBc = 1;
CiaControl.CsrIoaBypass = 0;
CiaControl.IoFlushReqEn = 0;
CiaControl.CpuFlushReqEn = 0;
CiaControl.ArbEv5En = 0;
//
// Old revisions of CIA should have ArbLink off since it doesn't work.
//
if (HalpCiaRevision < CIA_REVISION_3) {
CiaControl.EnArbLink = 0;
} else {
CiaControl.EnArbLink = 1;
}
CiaControl.RdType = 0;
CiaControl.RlType = 1;
CiaControl.RmType = 2;
CiaControl.EnDmaRdPerf = 0;
WRITE_CIA_REGISTER( &((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->CiaCtrl,
CiaControl.all );
//
// Initialize CIA Config. Turn on the performance enhancement features of
// CIA2. No-op for rev 1 CIA.
//
CiaConfig.all =
READ_CIA_REGISTER(
&((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->CiaCnfg );
CiaConfig.IoaBwen = 0;
CiaConfig.PciDwen = 1;
WRITE_CIA_REGISTER( &((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->CiaCnfg,
CiaConfig.all );
//
// Disable all of the scatter/gather windows.
//
Wbase.all = 0;
Wbase.Wen = 0;
WRITE_CIA_REGISTER( &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Wbase0,
Wbase.all );
WRITE_CIA_REGISTER( &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Wbase1,
Wbase.all );
WRITE_CIA_REGISTER( &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Wbase2,
Wbase.all );
WRITE_CIA_REGISTER( &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Wbase3,
Wbase.all );
//
// Invalidate all of the TLB Entries:
//
Tbia.all = 0;
Tbia.InvalidateType = InvalidateAll;
//
// Perform the invalidation.
//
WRITE_CIA_REGISTER( &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Tbia,
Tbia.all );
//
// Clear any pending error bits in the CIA_ERR register:
//
CiaError.all = 0; // Clear all bits
CiaError.CorErr = 1; // Correctable error
CiaError.UnCorErr = 1; // Uncorrectable error
CiaError.CpuPe = 1; // Ev5 bus parity error
CiaError.MemNem = 1; // Nonexistent memory error
CiaError.PciSerr = 1; // PCI bus serr detected
CiaError.PciPerr = 1; // PCI bus perr detected
CiaError.PciAddrPe = 1; // PCI bus address parity error
CiaError.RcvdMasAbt = 1; // Pci Master Abort
CiaError.RcvdTarAbt = 1; // Pci Target Abort
CiaError.PaPteInv = 1; // Invalid Pte
CiaError.FromWrtErr = 1; // Invalid write to flash rom
CiaError.IoaTimeout = 1; // Io Timeout occurred
CiaError.LostCorErr = 1; // Lost correctable error
CiaError.LostUnCorErr = 1; // Lost uncorrectable error
CiaError.LostCpuPe = 1; // Lost Ev5 bus parity error
CiaError.LostMemNem = 1; // Lost Nonexistent memory error
CiaError.LostPciPerr = 1; // Lost PCI bus perr detected
CiaError.LostPciAddrPe = 1; // Lost PCI bus address parity error
CiaError.LostRcvdMasAbt = 1; // Lost Pci Master Abort
CiaError.LostRcvdTarAbt = 1; // Lost Pci Target Abort
CiaError.LostPaPteInv = 1; // Lost Invalid Pte
CiaError.LostFromWrtErr = 1; // Lost Invalid write to flash rom
CiaError.LostIoaTimeout = 1; // Lost Io Timeout occurred
CiaError.ErrValid = 1; // Self explanatory
WRITE_CIA_REGISTER( &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaErr,
CiaError.all
);
#if defined(CIA_PASS1)
{
ULONG Allocated;
PTRANSLATION_ENTRY MapRegister;
ULONG MaxPhysicalAddress;
ULONG NumberOfPages;
BOOLEAN __64KAlignment;
ULONG i;
//
// Create a special scatter/gather window to use for diagnostic
// DMAs that we can use to insure that the TLB is flushed of any
// other entries.
//
//
// Allocate a page of memory to hold the scatter/gather entries.
//
Allocated = HalpAllocPhysicalMemory( LoaderBlock,
MaxPhysicalAddress = __1GB - 1,
NumberOfPages = 1,
__64KAlignment = TRUE ); // FALSE );
//
// Make the first 32 entries in the new table valid, point them
// to the first 32 pages in memory.
//
MapRegister = (PTRANSLATION_ENTRY)(Allocated | KSEG0_BASE);
for( i=0; i < 32; i++ ){
ULONG Pfn = 0x700000 >> PAGE_SHIFT;
HAL_MAKE_VALID_TRANSLATION( MapRegister, Pfn );
MapRegister += 1;
Pfn += 1;
}
//
// Enable window 3 for the diagnostic dmas to the special scatter/gather
// table. Base of the window in PCI space is 32MB, size of the window
// is 1MB.
//
Wbase.all = 0;
Wbase.Wen = 1;
Wbase.SgEn = 1;
Wbase.Wbase = (ULONG)(__1MB * 32) >> 20;
Wmask.all = 0;
Wmask.Wmask = 0;
Tbase.all = 0;
Tbase.Tbase = (ULONG)(Allocated) >> 10;
WRITE_CIA_REGISTER( &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Tbase3,
Tbase.all );
WRITE_CIA_REGISTER( &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Wmask3,
Wmask.all );
WRITE_CIA_REGISTER( &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Wbase3,
Wbase.all );
}
#endif //CIA_PASS1
CiaInitialized = TRUE;
}
VOID
HalpCiaInitializeSfwWindow(
PWINDOW_CONTROL_REGISTERS WindowRegisters,
CIA_WINDOW_NUMBER WindowNumber
)
/*++
Routine Description:
Initialize the DMA Control software window registers for the specified
DMA Window.
Arguments:
WindowRegisters - Supplies a pointer to the software window control.
WindowNumber - Supplies the window number initialized. (0 = Isa Dma
Window, 1 = Master Dma Window).
Return Value:
None.
--*/
{
switch( WindowNumber ){
//
// The ISA DMA Window.
//
case CiaIsaWindow:
WindowRegisters->WindowBase = (PVOID)ISA_DMA_WINDOW_BASE;
WindowRegisters->WindowSize = ISA_DMA_WINDOW_SIZE;
WindowRegisters->TranslatedBaseRegister =
&((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Tbase1;
WindowRegisters->WindowBaseRegister =
&((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Wbase1;
WindowRegisters->WindowMaskRegister =
&((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Wmask1;
WindowRegisters->WindowTbiaRegister =
&((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Tbia;
break;
case CiaMasterWindow:
WindowRegisters->WindowBase = (PVOID)MASTER_DMA_WINDOW_BASE;
WindowRegisters->WindowSize = MASTER_DMA_WINDOW_SIZE;
WindowRegisters->TranslatedBaseRegister =
&((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Tbase0;
WindowRegisters->WindowBaseRegister =
&((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Wbase0;
WindowRegisters->WindowMaskRegister =
&((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Wmask0;
WindowRegisters->WindowTbiaRegister =
&((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Tbia;
break;
default:
#if HALDBG
DbgPrint( "CiaInitializeSfwWindow: Bad Window Number = %x\n",
WindowNumber );
#endif //HALDBG
break;
}
return;
}
VOID
HalpCiaProgramDmaWindow(
PWINDOW_CONTROL_REGISTERS WindowRegisters,
PVOID MapRegisterBase
)
/*++
Routine Description:
Program the control windows in the hardware so that DMA can be started
to the DMA window.
Arguments:
WindowRegisters - Supplies a pointer to the software window register
control structure.
MapRegisterBase - Supplies the logical address of the scatter/gather
array in system memory.
Return Value:
None.
--*/
{
CIA_WBASE Wbase;
CIA_TBASE Tbase;
CIA_WMASK Wmask;
//
// Program the windows as specified by the caller.
//
Wbase.all = 0;
Wbase.Wen = 1;
Wbase.SgEn = 1;
Wbase.Wbase = (ULONG)(WindowRegisters->WindowBase) >> 20;
Wmask.all = 0;
Wmask.Wmask = (WindowRegisters->WindowSize >> 20) - 1;
Tbase.all = 0;
Tbase.Tbase = (ULONG)MapRegisterBase >> 10;
//
// Dump the CIA registers.
//
#if HALDBG
DumpCia( CiaScatterGatherRegisters );
#endif //HALDBG
//
// Clear the window base, temporarily disabling transactions to this
// DMA window.
//
WRITE_CIA_REGISTER( WindowRegisters->WindowBaseRegister, 0 );
//
// Now program the window by writing the translated base, then the size
// of the window in the mask register and finally the window base,
// enabling both the window and scatter gather.
//
WRITE_CIA_REGISTER( WindowRegisters->TranslatedBaseRegister,
Tbase.all );
WRITE_CIA_REGISTER( WindowRegisters->WindowMaskRegister,
Wmask.all );
WRITE_CIA_REGISTER( WindowRegisters->WindowBaseRegister,
Wbase.all );
//
// Flush the volatile entries in the CIA's scatter/gather Tlb.
//
HalpCiaInvalidateTlb( WindowRegisters, InvalidateVolatile );
//
// Dump the CIA registers.
//
#if HALDBG
DumpCia( CiaScatterGatherRegisters | CiaGeneralRegisters );
#endif //HALDBG
return;
}
VOID
HalpCiaInvalidateTlb(
PWINDOW_CONTROL_REGISTERS WindowRegisters,
CIA_INVALIDATE_TYPE InvalidateType
)
/*++
Routine Description:
Invalidate the DMA Scatter/Gather TLB in the CIA. The TLB is invalidated
whenever the scatter/gather translation entries are modified.
Arguments:
WindowRegisters - Supplies a pointer to the software window register
control structure.
InvalidateType - Supplies the type of invalidate the caller requires.
Return Value:
None.
--*/
{
//
// Perform the invalidation based on the pass of the CIA.
//
if( HalpCiaRevision == CIA_REVISION_1 ){
ULONG LoopbackAddress;
ULONG i;
//
// Perform 8 reads to PCI Dense space through the special loopback
// scatter/gather window to invalidate each entry in the CIA TLB.
// Each TLB fill prefetches 4 entries so our 8 reads must each be
// 32K bytes apart.
//
LoopbackAddress = __1MB * 32;
HalpMb();
for( i=0; i < 8; i++ ){
ULONG dummy;
dummy = READ_REGISTER_ULONG( (PULONG)LoopbackAddress );
LoopbackAddress += __1K * 32;
}
HalpMb();
} else {
CIA_TBIA Tbia;
//
// Set the invalidate as specified by the flush type.
//
Tbia.all = 0;
Tbia.InvalidateType = InvalidateType;
//
// Perform the invalidation.
//
WRITE_CIA_REGISTER( WindowRegisters->WindowTbiaRegister, Tbia.all );
} //end if( HalpCiaRevision == CIA_REVISION_1 )
}
#if HALDBG
VOID
DumpCia(
CIA_REGISTER_CLASS RegistersToDump
)
/*++
Routine Description:
Read the interesting Cia registers and print them to the debug port.
Arguments:
None.
Return Value:
None.
--*/
{
PVOID RegisterQva;
ULONG Value;
DbgPrint( "CIA Register Dump: \n" );
//
// Dump the CIA General Control registers.
//
if( (RegistersToDump & CiaGeneralRegisters) != 0 ){
RegisterQva = &((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->CiaRevision;
Value = READ_CIA_REGISTER( RegisterQva );
DbgPrint( "CiaRevision = 0x%x\n", Value );
RegisterQva = &((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->PciLat;
Value = READ_CIA_REGISTER( RegisterQva );
DbgPrint( "PciLat = 0x%x\n", Value );
RegisterQva = &((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->CiaCtrl;
Value = READ_CIA_REGISTER( RegisterQva );
DbgPrint( "CiaCtrl = 0x%x\n", Value );
RegisterQva = &((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->CiaCnfg;
Value = READ_CIA_REGISTER( RegisterQva );
DbgPrint( "CiaCnfg = 0x%x\n", Value );
RegisterQva = &((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->HaeMem;
Value = READ_CIA_REGISTER( RegisterQva );
DbgPrint( "HaeMem = 0x%x\n", Value );
RegisterQva = &((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->HaeIo;
Value = READ_CIA_REGISTER( RegisterQva );
DbgPrint( "HaeIo = 0x%x\n", Value );
RegisterQva = &((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->ConfigType;
Value = READ_CIA_REGISTER( RegisterQva );
DbgPrint( "ConfigType = 0x%x\n", Value );
RegisterQva = &((PCIA_GENERAL_CSRS)(CIA_GENERAL_CSRS_QVA))->CackEn;
Value = READ_CIA_REGISTER( RegisterQva );
DbgPrint( "CackEn = 0x%x\n", Value );
}
//
// Dump the CIA Error registers.
//
if( (RegistersToDump & CiaErrorRegisters) != 0 ){
RegisterQva = &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CpuErr0;
Value = READ_CIA_REGISTER( RegisterQva );
DbgPrint( "CpuErr0 = 0x%x\n", Value );
RegisterQva = &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CpuErr1;
Value = READ_CIA_REGISTER( RegisterQva );
DbgPrint( "CpuErr1 = 0x%x\n", Value );
RegisterQva = &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaErr;
Value = READ_CIA_REGISTER( RegisterQva );
DbgPrint( "CiaErr = 0x%x\n", Value );
RegisterQva = &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaStat;
Value = READ_CIA_REGISTER( RegisterQva );
DbgPrint( "CiaStat = 0x%x\n", Value );
RegisterQva = &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->ErrMask;
Value = READ_CIA_REGISTER( RegisterQva );
DbgPrint( "ErrMask = 0x%x\n", Value );
RegisterQva = &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->CiaSyn;
Value = READ_CIA_REGISTER( RegisterQva );
DbgPrint( "CiaSyn = 0x%x\n", Value );
RegisterQva = &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->MemErr0;
Value = READ_CIA_REGISTER( RegisterQva );
DbgPrint( "MemErr0 = 0x%x\n", Value );
RegisterQva = &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->MemErr1;
Value = READ_CIA_REGISTER( RegisterQva );
DbgPrint( "MemErr1 = 0x%x\n", Value );
RegisterQva = &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->PciErr0;
Value = READ_CIA_REGISTER( RegisterQva );
DbgPrint( "PciErr0 = 0x%x\n", Value );
RegisterQva = &((PCIA_ERROR_CSRS)(CIA_ERROR_CSRS_QVA))->PciErr1;
Value = READ_CIA_REGISTER( RegisterQva );
DbgPrint( "PciErr1 = 0x%x\n", Value );
}
//
// Dump the PCI Scatter/Gather registers.
//
if( (RegistersToDump & CiaScatterGatherRegisters) != 0 ){
RegisterQva = &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Tbia;
Value = READ_CIA_REGISTER( RegisterQva );
DbgPrint( "Tbia = 0x%x\n", Value );
RegisterQva = &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Wbase0;
Value = READ_CIA_REGISTER( RegisterQva );
DbgPrint( "Wbase0 = 0x%x\n", Value );
RegisterQva = &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Wmask0;
Value = READ_CIA_REGISTER( RegisterQva );
DbgPrint( "Wmask0 = 0x%x\n", Value );
RegisterQva = &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Tbase0;
Value = READ_CIA_REGISTER( RegisterQva );
DbgPrint( "Tbase0 = 0x%x\n", Value );
RegisterQva = &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Wbase1;
Value = READ_CIA_REGISTER( RegisterQva );
DbgPrint( "Wbase1 = 0x%x\n", Value );
RegisterQva = &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Wmask1;
Value = READ_CIA_REGISTER( RegisterQva );
DbgPrint( "Wmask1 = 0x%x\n", Value );
RegisterQva = &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Tbase1;
Value = READ_CIA_REGISTER( RegisterQva );
DbgPrint( "Tbase1 = 0x%x\n", Value );
RegisterQva = &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Wbase2;
Value = READ_CIA_REGISTER( RegisterQva );
DbgPrint( "Wbase2 = 0x%x\n", Value );
RegisterQva = &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Wmask2;
Value = READ_CIA_REGISTER( RegisterQva );
DbgPrint( "Wmask2 = 0x%x\n", Value );
RegisterQva = &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Tbase2;
Value = READ_CIA_REGISTER( RegisterQva );
DbgPrint( "Tbase2 = 0x%x\n", Value );
RegisterQva = &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Wbase3;
Value = READ_CIA_REGISTER( RegisterQva );
DbgPrint( "Wbase3 = 0x%x\n", Value );
RegisterQva = &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Wmask3;
Value = READ_CIA_REGISTER( RegisterQva );
DbgPrint( "Wmask3 = 0x%x\n", Value );
RegisterQva = &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Tbase3;
Value = READ_CIA_REGISTER( RegisterQva );
DbgPrint( "Tbase3 = 0x%x\n", Value );
RegisterQva = &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->Dac;
Value = READ_CIA_REGISTER( RegisterQva );
DbgPrint( "Dac = 0x%x\n", Value );
RegisterQva = &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->LtbTag0;
Value = READ_CIA_REGISTER( RegisterQva );
DbgPrint( "LtbTag0 = 0x%x\n", Value );
RegisterQva = &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->LtbTag1;
Value = READ_CIA_REGISTER( RegisterQva );
DbgPrint( "LtbTag1 = 0x%x\n", Value );
RegisterQva = &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->LtbTag2;
Value = READ_CIA_REGISTER( RegisterQva );
DbgPrint( "LtbTag2 = 0x%x\n", Value );
RegisterQva = &((PCIA_SG_CSRS)(CIA_SG_CSRS_QVA))->LtbTag3;
Value = READ_CIA_REGISTER( RegisterQva );
DbgPrint( "LtbTag3 = 0x%x\n", Value );
}
DbgPrint( "--end CIA Register dump\n\n" );
return;
}
#endif //HALDBG