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

658 lines
12 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) 1993 Digital Equipment Corporation
Module Name:
lca4.c
Abstract:
This module implements functions that are specific to the LCA4
microprocessor.
Author:
Joe Notarangelo 20-Oct-1993
Environment:
Kernel mode
Revision History:
--*/
#include "halp.h"
#include "lca4.h"
#include "axp21066.h"
#ifndef AXP_FIRMWARE
VOID
DumpIoc(
VOID
);
#endif
//
// Globals
//
//
// Parity checking is a tri-state variable, unknown == all f's. Which means
// Keep checking disabled until we can determine what we want to set it to,
// which then means 1 or 0.
//
extern ULONG HalDisablePCIParityChecking;
#ifdef AXP_FIRMWARE
//
// Put these functions in the discardable text section.
//
//
// Local function prototypes
//
ULONG
HalpDetermineLca4Revision(
VOID
);
VOID
HalpLca4MapAddressSpaces(
VOID
);
ULONG
HalpLca4Revision(
VOID
);
ULONGLONG
HalpLca4IocTbTagPhysical(
VOID
);
ULONGLONG
HalpLca4PciIntAckPhysical(
VOID
);
ULONGLONG
HalpLca4PciIoPhysical(
VOID
);
ULONGLONG
HalpLca4PciDensePhysical(
VOID
);
#pragma alloc_text(DISTEXT, HalpDetermineLca4Revision)
#pragma alloc_text(DISTEXT, HalpLca4MapAddressSpaces)
#pragma alloc_text(DISTEXT, HalpLca4Revision)
#pragma alloc_text(DISTEXT, HalpLca4IocTbTagPhysical)
#pragma alloc_text(DISTEXT, HalpLca4PciIntAckPhysical)
#pragma alloc_text(DISTEXT, HalpLca4PciIoPhysical)
#pragma alloc_text(DISTEXT, HalpLca4PciDensePhysical)
#endif // AXP_FIRMWARE
ULONG
HalpDetermineLca4Revision(
VOID
)
/*++
Routine Description:
Determine the revision of the LCA4 processor we are currently executing.
Arguments:
None.
Return Value:
Return the recognized revision of the LCA4 processor executing.
--*/
{
CAR_21066 Car;
ULONG Revision;
//
// Pass 1 and Pass 2 LCA processors can be distinguished by the
// PWR bit of the Cache Register (CAR). For Pass 1 the bit is RAZ
// while for Pass 2 the bit is read/write.
//
// Read the current value of the CAR. If it is 1, then we know that
// it is Pass 2. Else, set the PWR bit and write it back.
// Then read CAR again. If PWR is still set then we are executing on
// Pass 2. Don't forget to reset the PWR bit before finishing.
//
Car.all.QuadPart = READ_MEMC_REGISTER(
&((PLCA4_MEMC_CSRS)(0))->CacheControl );
if( Car.Pwr == 1 ) {
Revision = Lca4Pass2;
} else {
Car.Pwr = 1;
WRITE_MEMC_REGISTER( &((PLCA4_MEMC_CSRS)(0))->CacheControl,
Car.all.QuadPart );
Car.all.QuadPart = READ_MEMC_REGISTER(
&((PLCA4_MEMC_CSRS)(0))->CacheControl );
if( Car.Pwr == 1 ){
Revision = Lca4Pass2;
} else {
Revision = Lca4Pass1;
}
Car.Pwr = 0;
WRITE_MEMC_REGISTER( &((PLCA4_MEMC_CSRS)(0))->CacheControl,
Car.all.QuadPart );
}
return Revision;
}
//
// Define the Revision variable for LCA4.
//
ULONG Lca4Revision;
//
// Define the Physical Address space variables for LCA4.
//
ULONGLONG Lca4IocTbTagPhysical;
ULONGLONG Lca4PciIntAckPhysical;
ULONGLONG Lca4PciIoPhysical;
ULONGLONG Lca4PciDensePhysical;
VOID
HalpLca4MapAddressSpaces(
VOID
)
/*++
Routine Description:
Map the address spaces of the LCA4 dependent upon which revision
of the chip is executing.
Arguments:
None.
Return Value:
None.
--*/
{
Lca4Revision = HalpDetermineLca4Revision();
switch (Lca4Revision){
//
// Pass 1 LCA4
//
case Lca4Pass1:
Lca4IocTbTagPhysical = LCA4_PASS1_IOC_TBTAG_PHYSICAL;
Lca4PciIntAckPhysical = LCA4_PASS1_PCI_INTACK_BASE_PHYSICAL;
Lca4PciIoPhysical = LCA4_PASS1_PCI_IO_BASE_PHYSICAL;
Lca4PciDensePhysical = 0;
break;
//
// Pass 2 LCA4
//
case Lca4Pass2:
Lca4IocTbTagPhysical = LCA4_PASS2_IOC_TBTAG_PHYSICAL;
Lca4PciIntAckPhysical = LCA4_PASS2_PCI_INTACK_BASE_PHYSICAL;
Lca4PciIoPhysical = LCA4_PASS2_PCI_IO_BASE_PHYSICAL;
Lca4PciDensePhysical = LCA4_PASS2_PCI_DENSE_BASE_PHYSICAL;
break;
#if (DBG) || (HALDBG)
default:
DbgPrint( "Unrecognized LCA4 Revision = %x (execution is hopeless)\n",
Lca4Revision );
DbgBreakPoint();
#endif //DBG || HALDBG
}
return;
}
//
// The following routines could be in-lined (it that were supported) or
// made into macros to save space (time isn't any issue with these values).
// To do so the variables above would have to be exported.
//
ULONG
HalpLca4Revision(
VOID
)
/*++
Routine Description:
Return the version of the LCA4 processor.
Arguments:
None.
Return Value:
The version of the LCA4 processor.
--*/
{
return Lca4Revision;
}
ULONGLONG
HalpLca4IocTbTagPhysical(
VOID
)
/*++
Routine Description:
Return the base address of the IOC TB Tag registers on the currently
executing LCA4 processor.
Arguments:
None.
Return Value:
The base physical address of the IOC TB Tag registers.
--*/
{
return Lca4IocTbTagPhysical;
}
ULONGLONG
HalpLca4PciIntAckPhysical(
VOID
)
/*++
Routine Description:
Return the base physical address of PCI Interrupt Acknowledge space
on the currently executing LCA4 processor.
Arguments:
None.
Return Value:
The base physical address of PCI Interrupt Acknowledge.
--*/
{
return Lca4PciIntAckPhysical;
}
ULONGLONG
HalpLca4PciIoPhysical(
VOID
)
/*++
Routine Description:
Return the base physical address of PCI I/O space on the currently
executing LCA4 processor.
Arguments:
None.
Return Value:
The base physical address of PCI I/O space.
--*/
{
return Lca4PciIoPhysical;
}
ULONGLONG
HalpLca4PciDensePhysical(
VOID
)
/*++
Routine Description:
Return the base physical address of PCI Dense Memory space on the
currently executing LCA4 processor.
Arguments:
None.
Return Value:
The base physical address of PCI Dense Memory space.
--*/
{
return Lca4PciDensePhysical;
}
#if !defined(AXP_FIRMWARE)
VOID
HalpLca4InitializeSfwWindow(
PWINDOW_CONTROL_REGISTERS WindowRegisters,
LCA4_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 Lca4IsaWindow:
WindowRegisters->WindowBase = (PVOID)ISA_DMA_WINDOW_BASE;
WindowRegisters->WindowSize = ISA_DMA_WINDOW_SIZE;
WindowRegisters->TranslatedBaseRegister =
&((PLCA4_IOC_CSRS)(LCA4_IOC_BASE_QVA))->TranslatedBase0;
WindowRegisters->WindowBaseRegister =
&((PLCA4_IOC_CSRS)(LCA4_IOC_BASE_QVA))->WindowBase0;
WindowRegisters->WindowMaskRegister =
&((PLCA4_IOC_CSRS)(LCA4_IOC_BASE_QVA))->WindowMask0;
WindowRegisters->WindowTbiaRegister =
&((PLCA4_IOC_CSRS)(LCA4_IOC_BASE_QVA))->Tbia;
break;
//
// The Master DMA Window.
//
case Lca4MasterWindow:
WindowRegisters->WindowBase = (PVOID)MASTER_DMA_WINDOW_BASE;
WindowRegisters->WindowSize = MASTER_DMA_WINDOW_SIZE;
WindowRegisters->TranslatedBaseRegister =
&((PLCA4_IOC_CSRS)(LCA4_IOC_BASE_QVA))->TranslatedBase1;
WindowRegisters->WindowBaseRegister =
&((PLCA4_IOC_CSRS)(LCA4_IOC_BASE_QVA))->WindowBase1;
WindowRegisters->WindowMaskRegister =
&((PLCA4_IOC_CSRS)(LCA4_IOC_BASE_QVA))->WindowMask1;
WindowRegisters->WindowTbiaRegister =
&((PLCA4_IOC_CSRS)(LCA4_IOC_BASE_QVA))->Tbia;
break;
default:
#if DBG
DbgPrint( "Lca4InitializeSfwWindow: Bad Window Number = %x\n",
WindowNumber );
#endif //DBG
break;
}
return;
}
VOID
HalpLca4ProgramDmaWindow(
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.
--*/
{
LCA4_IOC_WMASK WindowMask;
LCA4_IOC_WBASE WindowBase;
LCA4_IOC_TBEN TbEnable;
LCA4_IOC_PCIPD PciPD;
LCA4_IOC_TBASE TranslatedBase;
PVOID RegisterQva;
WindowBase.Reserved1 = 0;
WindowBase.Reserved2 = 0;
WindowBase.Sg = 1;
WindowBase.Wen = 1;
WindowBase.BaseValue = (ULONG)(WindowRegisters->WindowBase) >> 20;
WindowMask.Reserved1 = 0;
WindowMask.Reserved = 0;
WindowMask.MaskValue = (WindowRegisters->WindowSize >> 20) - 1;
TranslatedBase.Reserved1 = 0;
TranslatedBase.Reserved = 0;
TranslatedBase.TBase = (ULONG)(MapRegisterBase) >> 10;
#if DBG
//
// Dump the EPIC registers.
//
DumpIoc();
#endif //DBG
//
// Clear the window base, temporarily disabling transactions to this
// DMA window.
//
WRITE_IOC_REGISTER( WindowRegisters->WindowBaseRegister, (ULONGLONG)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_IOC_REGISTER( WindowRegisters->TranslatedBaseRegister,
*(PULONGLONG)&TranslatedBase );
WRITE_IOC_REGISTER( WindowRegisters->WindowMaskRegister,
*(PULONGLONG)&WindowMask );
WRITE_IOC_REGISTER( WindowRegisters->WindowBaseRegister,
*(PULONGLONG)&WindowBase );
//
// Invalidate any translations that might have existed for this window.
//
WRITE_IOC_REGISTER( WindowRegisters->WindowTbiaRegister, (ULONGLONG)0 );
//
// Enable the translation buffer inside of the IOC.
//
RtlZeroMemory( &TbEnable, sizeof(LCA4_IOC_TBEN) );
TbEnable.Ten = 1;
WRITE_IOC_REGISTER( &((PLCA4_IOC_CSRS)(LCA4_IOC_BASE_QVA))->TbEnable,
*(PULONGLONG)&TbEnable );
//
// Tri state parity checking - keep disabled if not determined
// yet. otherwise, Whack the PCI parity disable bit with the stored
// value
//
RtlZeroMemory( &PciPD, sizeof(LCA4_IOC_PCIPD) );
if (HalDisablePCIParityChecking == 0xffffffff) {
PciPD.Par = 1;
} else {
PciPD.Par = HalDisablePCIParityChecking;
}
WRITE_IOC_REGISTER( &((PLCA4_IOC_CSRS)(LCA4_IOC_BASE_QVA))->PciParityDisable,
*(PULONGLONG)&PciPD );
#if DBG
//
// Dump the IOC registers.
//
DumpIoc();
#endif //DBG
return;
}
ULONGLONG
READ_IOC_REGISTER(
PVOID
);
#if DBG
VOID
DumpIoc(
VOID
)
/*++
Routine Description:
Read the interesting IOC registers and print them to the debug port.
Arguments:
None.
Return Value:
None.
--*/
{
PVOID RegisterQva;
ULONGLONG Value;
DbgPrint( "Dumping the IOC registers\n" );
RegisterQva =
&((PLCA4_IOC_CSRS)(LCA4_IOC_BASE_QVA))->IocStat0;
Value = READ_IOC_REGISTER( RegisterQva );
DbgPrint( "IOSTAT[0] = %Lx\n", Value );
RegisterQva =
&((PLCA4_IOC_CSRS)(LCA4_IOC_BASE_QVA))->IocStat1;
Value = READ_IOC_REGISTER( RegisterQva );
DbgPrint( "IOSTAT[1] = %Lx\n", Value );
DbgPrint( "--end IOC dump\n\n" );
return;
}
#endif //DBG
#endif //!AXP_FIRMWARE