2520 lines
63 KiB
C
2520 lines
63 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1990 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
selftest.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module contains the routines that perform the selftest of
|
|||
|
the IO devices.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Lluis Abello (lluis) 03-Jan-1991
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "fwp.h"
|
|||
|
#include "iodevice.h"
|
|||
|
#include "led.h"
|
|||
|
#include "selfmap.h"
|
|||
|
#include "selftest.h"
|
|||
|
#include "ioaccess.h"
|
|||
|
#include "fwstring.h"
|
|||
|
#include "stdio.h"
|
|||
|
|
|||
|
|
|||
|
typedef CACHEERR *PCACHEERR;
|
|||
|
|
|||
|
#define SetCursorPosition(Row,Column) \
|
|||
|
FwPrint("\x9B"#Row";"#Column"H")
|
|||
|
#define MoveCursorLeft(Spaces) \
|
|||
|
FwPrint("\x9B"#Spaces"D")
|
|||
|
#define ClearScreen() FwPrint("\x9B""2J");
|
|||
|
|
|||
|
PUCHAR TranslationTable = "0123456789ABCDEF";
|
|||
|
UCHAR StationAddress[6];
|
|||
|
BOOLEAN ProcessorBEnabled = FALSE;
|
|||
|
BOOLEAN ValidEthernetAddress; // True if station address is OK False Otherwise
|
|||
|
BOOLEAN ConfigurationBit; // read value from diagnostic register
|
|||
|
BOOLEAN LoopOnError; // read value from diagnostic register
|
|||
|
BOOLEAN IgnoreErrors; // read value from diagnostic register
|
|||
|
volatile LONG TimerTicks; // Counter for timeouts
|
|||
|
BOOLEAN KeyboardInitialized; // True if the keyboard is initialized
|
|||
|
BOOLEAN MctadrRev2; // True if this is a rev2 ASIC
|
|||
|
|
|||
|
PRTL_ALLOCATE_STRING_ROUTINE RtlAllocateStringRoutine =
|
|||
|
(PRTL_ALLOCATE_STRING_ROUTINE)FwAllocatePool;
|
|||
|
PRTL_FREE_STRING_ROUTINE RtlFreeStringRoutine = FwpFreeStub;
|
|||
|
|
|||
|
|
|||
|
#ifndef DUO
|
|||
|
//
|
|||
|
// Table of memory size for each valid configuration.
|
|||
|
//
|
|||
|
UCHAR ConfigurationSize[64]=
|
|||
|
{ 0, 0, 0, 0, 4, 16, 0, 0,
|
|||
|
0, 0, 0, 0, 8, 20, 20, 32,
|
|||
|
0, 0, 0, 0, 8, 32, 0, 0,
|
|||
|
0, 0, 0, 0, 12, 36, 24, 48,
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|||
|
0, 0, 0, 0, 16, 40, 40, 64
|
|||
|
};
|
|||
|
|
|||
|
USHORT FConfigurationSize[256]=
|
|||
|
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
|||
|
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0
|
|||
|
4, 16, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2
|
|||
|
8, 20, 68, 0, 0, 32, 80, 0, 0, 0,128, 0, 0, 0, 0, 0, // 3
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4
|
|||
|
8, 32,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 5
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6
|
|||
|
12, 36,132, 0, 0, 48,144, 0, 0, 0,192, 0, 0, 0, 0, 0, // 7
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A
|
|||
|
0, 24, 72, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E
|
|||
|
16, 40,136, 0, 0, 64,160, 0, 0, 0,256, 0, 0, 0, 0, 0 // F
|
|||
|
};
|
|||
|
#else
|
|||
|
//
|
|||
|
// This table indexed with the low 4 bits of the MemoryGroup config register,
|
|||
|
// returns the size of memory installed in the group in Megabytes.
|
|||
|
//
|
|||
|
UCHAR GroupSize[16]=
|
|||
|
{ 0, 0, 0, 0, // No SIMM installes
|
|||
|
4, 16, 64, 0, // Single Sided
|
|||
|
0, 0, 0, 0, // Reserved
|
|||
|
8, 32,128, 0 // Double Sided.
|
|||
|
};
|
|||
|
#endif
|
|||
|
//
|
|||
|
// This variable is initialized to the size of the memory in Megabytes
|
|||
|
//
|
|||
|
|
|||
|
ULONG MemorySize;
|
|||
|
|
|||
|
ULONG KSEG_BASE[3]={KSEG1_BASE,KSEG0_BASE,KSEG0_BASE};
|
|||
|
ULONG XOR_KSEG_WRITE[3]={0x00000000,0xFFFFFFFF,0x01010101};
|
|||
|
ULONG XOR_KSEG_READ[3]={0x00000000,0xFFFFFFFF,0x01010101};
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Declare function prototypes.
|
|||
|
//
|
|||
|
VOID
|
|||
|
ReportJazzCacheErrorException(
|
|||
|
IN ULONG CacheErr
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
ReportDuoCacheErrorException(
|
|||
|
IN ULONG CacheErr
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
LoadDoubleWord(
|
|||
|
IN ULONG Address,
|
|||
|
OUT PVOID Result
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
InitializePCR(
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
FwBootSystem(
|
|||
|
IN VOID
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
RomSelftest(
|
|||
|
IN VOID
|
|||
|
);
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
SerialBootWrite(
|
|||
|
CHAR Char,
|
|||
|
ULONG SP
|
|||
|
);
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
ValidNvram(
|
|||
|
OUT PUCHAR StationAddress
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
WriteMemoryAddressTest(
|
|||
|
ULONG StartAddress,
|
|||
|
ULONG Size,
|
|||
|
ULONG Xorpattern
|
|||
|
);
|
|||
|
|
|||
|
PULONG
|
|||
|
CheckMemoryAddressTest(
|
|||
|
ULONG StartAddress,
|
|||
|
ULONG Size,
|
|||
|
ULONG Xorpattern,
|
|||
|
ULONG LedDisplayValue
|
|||
|
);
|
|||
|
VOID
|
|||
|
WriteVideoMemoryAddressTest(
|
|||
|
ULONG StartAddress,
|
|||
|
ULONG Size
|
|||
|
);
|
|||
|
ULONG
|
|||
|
CheckVideoMemoryAddressTest(
|
|||
|
ULONG StartAddress,
|
|||
|
ULONG Size
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
SetSmallDCacheBlock(
|
|||
|
IN VOID
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
WildZeroMemory(
|
|||
|
ULONG StartAddress,
|
|||
|
ULONG Size
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
SerialBootSetup(
|
|||
|
IN ULONG FileId
|
|||
|
);
|
|||
|
VOID
|
|||
|
FwSelftest(
|
|||
|
IN ULONG Cause,
|
|||
|
IN ULONG Arg1
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
FwSelftest(
|
|||
|
IN ULONG Cause,
|
|||
|
IN ULONG Arg1
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine is the c routine called from the ROM. It must be placed
|
|||
|
at the beginning of the C code because the ROM copies the code from this
|
|||
|
point to the end and then jumps to it.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Cause - 0 on a normal reset/powerup
|
|||
|
1 on a softreset.
|
|||
|
2 if an NMI occurred.
|
|||
|
3 if a cache error/parity occurred.
|
|||
|
|
|||
|
Arg1 - Error EPC if an NMI occurred
|
|||
|
CacheErr register if a cache error occurred
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Never returns.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ULONG IntSrc;
|
|||
|
#ifdef DUO
|
|||
|
ULONG Config;
|
|||
|
ULONG MemConfig;
|
|||
|
LONG Group;
|
|||
|
CHAR Diag;
|
|||
|
#endif
|
|||
|
CHAR String[128];
|
|||
|
ULONG ProcessorBootStatus;
|
|||
|
|
|||
|
|
|||
|
#ifndef DUO
|
|||
|
//
|
|||
|
// Initialize MemorySize to the size of memory in MegaBytes. Look for the
|
|||
|
// MCT_ADR REV2 Map Prom bit in the configuration register, if there this
|
|||
|
// is a REV2, otherwise REV1.
|
|||
|
//
|
|||
|
|
|||
|
if (DMA_CONTROL->Configuration.Long & 0x400) {
|
|||
|
MemorySize = FConfigurationSize[DMA_CONTROL->Configuration.Long & 0xFF];
|
|||
|
MctadrRev2 = TRUE;
|
|||
|
} else {
|
|||
|
MemorySize = ConfigurationSize[DMA_CONTROL->Configuration.Long & 0x3F];
|
|||
|
MctadrRev2 = FALSE;
|
|||
|
}
|
|||
|
|
|||
|
#else
|
|||
|
if (READ_REGISTER_ULONG(&DMA_CONTROL->WhoAmI.Long)) {
|
|||
|
if (Cause == 2) {
|
|||
|
//
|
|||
|
// NMI
|
|||
|
//
|
|||
|
sprintf(String,
|
|||
|
ST_NMI_MSG,
|
|||
|
Arg1
|
|||
|
);
|
|||
|
FwPrint(ST_PROCESSOR_B_MSG);
|
|||
|
FwPrint(String);
|
|||
|
FwPrint(FW_SYSTEM_HALT_MSG);
|
|||
|
for (;;) {
|
|||
|
}
|
|||
|
} else if (Cause == 3) {
|
|||
|
//
|
|||
|
// Cache error
|
|||
|
//
|
|||
|
} else {
|
|||
|
//
|
|||
|
// soft or cold reset.
|
|||
|
//
|
|||
|
ProcessorBMain();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
MemorySize = 0;
|
|||
|
|
|||
|
for(Group=0;Group < 4; Group++) {
|
|||
|
MemConfig = DMA_CONTROL->MemoryConfig[Group].Long;
|
|||
|
MemorySize += GroupSize[MemConfig&0xF]; // plus size of group.
|
|||
|
}
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// Set variables according to the bits in configuration register
|
|||
|
//
|
|||
|
|
|||
|
ConfigurationBit = FALSE;
|
|||
|
IgnoreErrors = FALSE;
|
|||
|
LoopOnError = FALSE;
|
|||
|
DisplayOutput = FALSE;
|
|||
|
SerialOutput = FALSE;
|
|||
|
KeyboardInitialized = FALSE;
|
|||
|
|
|||
|
//
|
|||
|
// Look for configuration register.
|
|||
|
//
|
|||
|
#ifdef DUO
|
|||
|
Diag=READ_REGISTER_UCHAR(DIAGNOSTIC_VIRTUAL_BASE);
|
|||
|
if ((Diag & LOOP_ON_ERROR_MASK) == 0) {
|
|||
|
LoopOnError = TRUE;
|
|||
|
}
|
|||
|
if ((Diag & CONFIGURATION_MASK) == 0) {
|
|||
|
ConfigurationBit = TRUE;
|
|||
|
}
|
|||
|
if ((Diag & IGNORE_ERRORS_MASK) == 0) {
|
|||
|
IgnoreErrors = TRUE;
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
// Diag=READ_REGISTER_UCHAR(DIAGNOSTIC_VIRTUAL_BASE) & DIAGNOSTIC_MASK;
|
|||
|
// switch (Diag) {
|
|||
|
// case 0: IgnoreErrors = TRUE;
|
|||
|
// break;
|
|||
|
// case (1<<7): LoopOnError = TRUE;
|
|||
|
// break;
|
|||
|
// case (1<<6): ConfigurationBit = TRUE;
|
|||
|
// break;
|
|||
|
// }
|
|||
|
|
|||
|
//
|
|||
|
// Set interrupt lines to a known state.
|
|||
|
//
|
|||
|
|
|||
|
WRITE_REGISTER_UCHAR(&SP1_WRITE->ModemControl,0x08);
|
|||
|
WRITE_REGISTER_UCHAR(&SP2_WRITE->ModemControl,0x08);
|
|||
|
#ifndef DUO
|
|||
|
WRITE_REGISTER_UCHAR(&FLOPPY_WRITE->DigitalOutput,0x08);
|
|||
|
#endif
|
|||
|
READ_REGISTER_UCHAR(&PARALLEL_READ->Status);
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the system parameter block.
|
|||
|
//
|
|||
|
|
|||
|
SYSTEM_BLOCK->Signature = 0x53435241;
|
|||
|
SYSTEM_BLOCK->Length = sizeof(SYSTEM_PARAMETER_BLOCK);
|
|||
|
SYSTEM_BLOCK->Version = ARC_VERSION;
|
|||
|
SYSTEM_BLOCK->Revision = ARC_REVISION;
|
|||
|
|
|||
|
//
|
|||
|
// Allocate the restart block.
|
|||
|
//
|
|||
|
|
|||
|
SYSTEM_BLOCK->RestartBlock = (PRESTART_BLOCK)((ULONG)((PUCHAR)SYSTEM_BLOCK + sizeof(SYSTEM_PARAMETER_BLOCK)) | KSEG1_BASE);
|
|||
|
|
|||
|
SYSTEM_BLOCK->DebugBlock = NULL;
|
|||
|
#ifdef DUO
|
|||
|
//
|
|||
|
// Link the second restart block for processor B.
|
|||
|
//
|
|||
|
SYSTEM_BLOCK->RestartBlock->NextRestartBlock = (PRESTART_BLOCK)(((ULONG)SYSTEM_BLOCK + sizeof(SYSTEM_PARAMETER_BLOCK) + sizeof(RESTART_BLOCK)) | KSEG1_BASE);
|
|||
|
|
|||
|
SYSTEM_BLOCK->RestartBlock->NextRestartBlock->NextRestartBlock = NULL;
|
|||
|
SYSTEM_BLOCK->FirmwareVector = (PVOID)((ULONG)((PUCHAR)SYSTEM_BLOCK + sizeof(SYSTEM_PARAMETER_BLOCK) + 2*sizeof(RESTART_BLOCK)) | KSEG1_BASE);
|
|||
|
#else
|
|||
|
SYSTEM_BLOCK->RestartBlock->NextRestartBlock = NULL;
|
|||
|
SYSTEM_BLOCK->FirmwareVector =
|
|||
|
(PVOID)((PUCHAR)SYSTEM_BLOCK + sizeof(SYSTEM_PARAMETER_BLOCK) + sizeof(RESTART_BLOCK));
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
SYSTEM_BLOCK->FirmwareVectorLength = (ULONG)MaximumRoutine * sizeof(ULONG);
|
|||
|
SYSTEM_BLOCK->VendorVectorLength = (ULONG)MaximumVendorRoutine * sizeof(ULONG);
|
|||
|
SYSTEM_BLOCK->VendorVector =
|
|||
|
(PVOID)(SYSTEM_BLOCK->FirmwareVector +
|
|||
|
SYSTEM_BLOCK->FirmwareVectorLength);
|
|||
|
|
|||
|
//
|
|||
|
// If the configuration bit is set, go to the serial port.
|
|||
|
//
|
|||
|
|
|||
|
PutLedDisplay(LED_NVRAM);
|
|||
|
if (ConfigurationBit) {
|
|||
|
//
|
|||
|
// Test the serial port if not a soft reset.
|
|||
|
//
|
|||
|
if (Cause == 0) {
|
|||
|
ExecuteTest((TestRoutine)RomSerialResetTest,LED_SERIAL_RESET);
|
|||
|
ExecuteTest((TestRoutine)RomSerial1RegistersTest,LED_SERIAL1_REG);
|
|||
|
ExecuteTest((TestRoutine)RomSerial2RegistersTest,LED_SERIAL2_REG);
|
|||
|
ExecuteTest((TestRoutine)RomSerial1LoopBackTest,LED_SERIAL1_LBACK);
|
|||
|
ExecuteTest((TestRoutine)RomSerial2LoopBackTest,LED_SERIAL2_LBACK);
|
|||
|
PutLedDisplay(LED_SERIAL_INIT);
|
|||
|
}
|
|||
|
//
|
|||
|
// Initialize the serial port as there is no configuration
|
|||
|
// data to initialize the video.
|
|||
|
//
|
|||
|
SerialBootSetup(COMPORT2_VIRTUAL_BASE);
|
|||
|
SerialOutput = TRUE;
|
|||
|
ClearScreen()
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// If there is a valid Ethernet station address, protect it.
|
|||
|
//
|
|||
|
|
|||
|
if (ValidNvram(StationAddress) == TRUE) {
|
|||
|
// WRITE_REGISTER_ULONG (&DMA_CONTROL->SystemSecurity.Long,READ_ONLY_DISABLE_WRITE);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Test the video memory.
|
|||
|
// Doesn't work for VXL
|
|||
|
//
|
|||
|
if (Cause == 0) {
|
|||
|
// ExecuteTest((TestRoutine)RomVideoMemory,LED_VIDEOMEM);
|
|||
|
PutLedDisplay(LED_VIDEO_CONTROLLER);
|
|||
|
}
|
|||
|
|
|||
|
//TEMPTEMP
|
|||
|
// if (DisplayBootInitialize() != ESUCCESS) {
|
|||
|
// //
|
|||
|
// // If video is broken and the NVRAM was ok and the config
|
|||
|
// // bit was not set do not attempt to write to the serial port.
|
|||
|
// // No output device is available, so hang.
|
|||
|
// //
|
|||
|
// PutLedDisplay((LED_BLINK << 16) | LED_VIDEO_CONTROLLER);
|
|||
|
// } else {
|
|||
|
// //
|
|||
|
// // Video is ready to display messages.
|
|||
|
// //
|
|||
|
// DisplayOutput=TRUE;
|
|||
|
// }
|
|||
|
//TEMPTEMP
|
|||
|
|
|||
|
DisplayBootInitialize();
|
|||
|
DisplayOutput=TRUE;
|
|||
|
}
|
|||
|
if (Cause == 2) {
|
|||
|
//
|
|||
|
// This is an NMI. Display a message and hang.
|
|||
|
//
|
|||
|
sprintf(String,
|
|||
|
ST_NMI_MSG,
|
|||
|
Arg1
|
|||
|
);
|
|||
|
FwPrint(String);
|
|||
|
//
|
|||
|
// Read The Interrupt source register and check the cause of the NMI.
|
|||
|
//
|
|||
|
#ifndef DUO
|
|||
|
IntSrc = READ_REGISTER_ULONG(&DMA_CONTROL->InterruptSource.Long);
|
|||
|
if (IntSrc & (1<<9)) {
|
|||
|
sprintf(String,
|
|||
|
ST_INVALID_ADDRESS_MSG,
|
|||
|
READ_REGISTER_ULONG(&DMA_CONTROL->InvalidAddress.Long)
|
|||
|
);
|
|||
|
FwPrint(String);
|
|||
|
}
|
|||
|
if (IntSrc & (1<<10)) {
|
|||
|
sprintf(String,
|
|||
|
ST_IO_CACHE_ADDRESS_MSG,
|
|||
|
READ_REGISTER_ULONG(&DMA_CONTROL->MemoryFailedAddress.Long)
|
|||
|
);
|
|||
|
FwPrint(String);
|
|||
|
}
|
|||
|
FwPrint(FW_SYSTEM_HALT_MSG);
|
|||
|
#else
|
|||
|
IntSrc = READ_REGISTER_ULONG(&DMA_CONTROL->NmiSource.Long);
|
|||
|
if (IntSrc & (1<<1)) {
|
|||
|
sprintf(String,
|
|||
|
ST_INVALID_ADDRESS_MSG,
|
|||
|
READ_REGISTER_ULONG(&DMA_CONTROL->InvalidAddress.Long)
|
|||
|
);
|
|||
|
FwPrint(String);
|
|||
|
}
|
|||
|
if (IntSrc & (1<<2)) {
|
|||
|
sprintf(String,
|
|||
|
ST_IO_CACHE_ADDRESS_MSG,
|
|||
|
READ_REGISTER_ULONG(&DMA_CONTROL->MemoryFailedAddress.Long)
|
|||
|
);
|
|||
|
FwPrint(String);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Notify processor B
|
|||
|
//
|
|||
|
WRITE_REGISTER_ULONG(&DMA_CONTROL->IpInterruptRequest.Long,2);
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// Hang blinking LED.
|
|||
|
//
|
|||
|
PutLedDisplay((LED_BLINK << 16) | LED_NMI);
|
|||
|
}
|
|||
|
if (Cause == 3) {
|
|||
|
#ifndef DUO
|
|||
|
ReportJazzCacheErrorException(Arg1);
|
|||
|
#else
|
|||
|
ReportDuoCacheErrorException(Arg1);
|
|||
|
#endif
|
|||
|
PutLedDisplay((LED_BLINK << 16) | LED_PARITY);
|
|||
|
}
|
|||
|
//
|
|||
|
// Reset the EISA bus. This is required because the EBC reset line on Jazz
|
|||
|
// is connected wrong.
|
|||
|
//
|
|||
|
|
|||
|
WRITE_REGISTER_UCHAR(&EISA_CONTROL->ExtendedNmiResetControl,0x01);
|
|||
|
FwStallExecution(10);
|
|||
|
WRITE_REGISTER_UCHAR(&EISA_CONTROL->ExtendedNmiResetControl,0x00);
|
|||
|
FwStallExecution(10);
|
|||
|
|
|||
|
if (Cause == 0) {
|
|||
|
//
|
|||
|
// Execute selftest if it's not a soft reset.
|
|||
|
//
|
|||
|
|
|||
|
FwPrintVersion();
|
|||
|
FwPrint(FW_CRLF_MSG);
|
|||
|
RomSelftest();
|
|||
|
} else {
|
|||
|
//
|
|||
|
// Need to initialize whatever the Selftest initializes.
|
|||
|
//
|
|||
|
PutLedDisplay(LED_KEYBOARD_CTRL);
|
|||
|
if (InitKeyboardController()) {
|
|||
|
FwPrint(ST_KEYBOARD_ERROR_MSG);
|
|||
|
}
|
|||
|
PutLedDisplay(LED_ISP);
|
|||
|
RomInitISP();
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Initialize master processor boot status.
|
|||
|
//
|
|||
|
ProcessorBootStatus = 0;
|
|||
|
((PBOOT_STATUS)&ProcessorBootStatus)->ProcessorReady = 1;
|
|||
|
((PBOOT_STATUS)&ProcessorBootStatus)->ProcessorRunning = 1;
|
|||
|
((PBOOT_STATUS)&ProcessorBootStatus)->ProcessorStart = 1;
|
|||
|
((PBOOT_STATUS)&ProcessorBootStatus)->BootStarted = 1;
|
|||
|
SYSTEM_BLOCK->RestartBlock->BootStatus = *((PBOOT_STATUS)&ProcessorBootStatus);
|
|||
|
|
|||
|
//
|
|||
|
// Zero the entire Memory.
|
|||
|
//
|
|||
|
PutLedDisplay(LED_ZEROMEM);
|
|||
|
|
|||
|
// WildZeroMemory(FW_TOP_ADDRESS,MEMORY_SIZE - FW_TOP_ADDRESS);
|
|||
|
RtlZeroMemory((PVOID)(FW_TOP_ADDRESS | KSEG0_BASE),MEMORY_SIZE - FW_TOP_ADDRESS);
|
|||
|
|
|||
|
#ifdef DUO
|
|||
|
|
|||
|
//
|
|||
|
// Initialize processor B boot status to not ready.
|
|||
|
//
|
|||
|
ProcessorBootStatus = 0;
|
|||
|
|
|||
|
//
|
|||
|
// Processor B Has been idle all this time. Check if it is present
|
|||
|
// and enable it.
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
Diag=READ_REGISTER_UCHAR(DIAGNOSTIC_VIRTUAL_BASE);
|
|||
|
|
|||
|
|
|||
|
if (!(Diag & 1)) {
|
|||
|
InitializePCR();
|
|||
|
FwPrint(ST_ENABLE_PROCESSOR_B_MSG);
|
|||
|
|
|||
|
// HalSweepDcache();
|
|||
|
//
|
|||
|
// TEMPTEMP we want to see all icache misses for now
|
|||
|
//
|
|||
|
// HalSweepIcache();
|
|||
|
|
|||
|
//
|
|||
|
// end TEMPTEMP
|
|||
|
//
|
|||
|
|
|||
|
Config = READ_REGISTER_ULONG(&DMA_CONTROL->Configuration.Long);
|
|||
|
WRITE_REGISTER_ULONG(&DMA_CONTROL->Configuration.Long,Config | ENABLE_PROCESSOR_B);
|
|||
|
|
|||
|
//
|
|||
|
// Processor B has been enabled. It will execute the rom code to initialize
|
|||
|
// its caches and then call ProcessorBMain from where it will issue
|
|||
|
// an Ip interrupt to us.
|
|||
|
//
|
|||
|
if (WaitForIpInterrupt(5000) == FALSE) {
|
|||
|
FwPrint(ST_TIMEOUT_PROCESSOR_B_MSG);
|
|||
|
} else {
|
|||
|
FwPrint(FW_OK_MSG);
|
|||
|
|
|||
|
//
|
|||
|
// If Processor B passes selftest, set processor ready bit in boot status.
|
|||
|
// Otherwise disable processor B
|
|||
|
//
|
|||
|
if (ProcessorBSelftest()) {
|
|||
|
((PBOOT_STATUS)&ProcessorBootStatus)->ProcessorReady = 1;
|
|||
|
ProcessorBEnabled = TRUE;
|
|||
|
}
|
|||
|
}
|
|||
|
//
|
|||
|
// If processor B failed selftest or never received its IP interrupt
|
|||
|
// Disable It.
|
|||
|
//
|
|||
|
if (!ProcessorBEnabled) {
|
|||
|
WRITE_REGISTER_ULONG(&DMA_CONTROL->Configuration.Long,Config);
|
|||
|
FwPrint(ST_PROCESSOR_B_DISABLED_MSG);
|
|||
|
}
|
|||
|
} else {
|
|||
|
FwPrint(ST_PROCESSOR_B_NOT_PRESENT_MSG);
|
|||
|
}
|
|||
|
|
|||
|
SYSTEM_BLOCK->RestartBlock->NextRestartBlock->BootStatus = *((PBOOT_STATUS)&ProcessorBootStatus);
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Disable all interrupts except IP and Local Device (for keyboard)
|
|||
|
//
|
|||
|
|
|||
|
WRITE_REGISTER_ULONG(&DMA_CONTROL->InterruptEnable.Long,
|
|||
|
(ENABLE_IP_INTERRUPTS | ENABLE_DEVICE_INTERRUPTS));
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
InitializePCR();
|
|||
|
PutLedDisplay(LED_BLANK<<4);
|
|||
|
FwBootSystem();
|
|||
|
|
|||
|
//
|
|||
|
// Hang if we come back.
|
|||
|
//
|
|||
|
|
|||
|
PutLedDisplay((LED_BLINK << 16) | 0xBB);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
RomSelftest (
|
|||
|
IN VOID
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine implements the self-test video phase.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ULONG Status;
|
|||
|
ULONG i,j,Test,CurrentK;
|
|||
|
LONG BlockSize;
|
|||
|
CHAR String[128];
|
|||
|
ULONG SIZE_OF_UNTESTED_MEMORY = MEMORY_SIZE-(FW_TOP_ADDRESS);
|
|||
|
|
|||
|
//TEMPTEMP
|
|||
|
PULONG Cached;
|
|||
|
|
|||
|
PutLedDisplay(LED_MAIN_MEMORY);
|
|||
|
|
|||
|
//
|
|||
|
// Display in the screen that the memory is being tested.
|
|||
|
//
|
|||
|
|
|||
|
SetCursorPosition(4,1);
|
|||
|
// sprintf(String,"Total memory is %d MBytes (%x)\r\n",MemorySize,DMA_CONTROL->Configuration.Long);
|
|||
|
// FwPrint(String);
|
|||
|
FwPrint(ST_MEMORY_TEST_MSG);
|
|||
|
|
|||
|
//
|
|||
|
// Zero the memory so that memtest can run cached.
|
|||
|
//
|
|||
|
//WildZeroMemory(FW_TOP_ADDRESS,SIZE_OF_UNTESTED_MEMORY);
|
|||
|
|
|||
|
for (Test=0;Test<1;Test++) { // 3!!
|
|||
|
//
|
|||
|
// display on the screen and LED that we start writing.
|
|||
|
//
|
|||
|
// SetCursorPosition(1,14);
|
|||
|
// sprintf(String,"%x",Test+1);
|
|||
|
// FwPrint(String);
|
|||
|
PutLedDisplay(LED_MAIN_MEMORY+Test+1);
|
|||
|
//
|
|||
|
// Write address test to the remaining untested memory
|
|||
|
//
|
|||
|
WriteMemoryAddressTest(KSEG0_BASE+FW_TOP_ADDRESS,
|
|||
|
SIZE_OF_UNTESTED_MEMORY,
|
|||
|
XOR_KSEG_WRITE[Test]);
|
|||
|
|
|||
|
//
|
|||
|
// Adjust first block size to align the tested memory to a block boundary
|
|||
|
//
|
|||
|
|
|||
|
BlockSize = KB_PER_TEST - TESTED_KB;
|
|||
|
while (BlockSize <= 0) {
|
|||
|
BlockSize += KB_PER_TEST;
|
|||
|
}
|
|||
|
CurrentK = TESTED_KB;
|
|||
|
do {
|
|||
|
|
|||
|
//
|
|||
|
// Display what has been tested so far.
|
|||
|
//
|
|||
|
|
|||
|
SetCursorPosition(4,15);
|
|||
|
sprintf(String,"%6d",CurrentK);
|
|||
|
FwPrint(String);
|
|||
|
Cached = CheckMemoryAddressTest(
|
|||
|
KSEG0_BASE + (CurrentK << 10), // cached address
|
|||
|
BlockSize << 10, // test up to next block boundary
|
|||
|
XOR_KSEG_READ[Test], // Xor Pattern
|
|||
|
(LED_BLINK << 16) + LED_MAIN_MEMORY);
|
|||
|
if (Cached != 0) {
|
|||
|
|
|||
|
//
|
|||
|
// Memory Error found.
|
|||
|
//
|
|||
|
|
|||
|
FwPrint(ST_MEMORY_ERROR_MSG);
|
|||
|
|
|||
|
if (LoopOnError) {
|
|||
|
// display in the LED that we start looping.
|
|||
|
PutLedDisplay((LED_LOOP_ERROR << 16)+LED_MAIN_MEMORY);
|
|||
|
for (;;) {
|
|||
|
CheckMemoryAddressTest(
|
|||
|
KSEG0_BASE + (CurrentK << 10), // cached address
|
|||
|
BlockSize << 10, // test up to next block boundary
|
|||
|
XOR_KSEG_READ[Test], // Xor Pattern
|
|||
|
(LED_BLINK << 16) + LED_MAIN_MEMORY);
|
|||
|
}
|
|||
|
} else {
|
|||
|
FwPrint(ST_HANG_MSG);
|
|||
|
// hang blinking the LED
|
|||
|
PutLedDisplay((LED_BLINK << 16) + LED_MAIN_MEMORY + Test + 1);
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
CurrentK += BlockSize;
|
|||
|
BlockSize = KB_PER_TEST;
|
|||
|
} while (CurrentK < KB_OF_MEMORY);
|
|||
|
|
|||
|
//
|
|||
|
// display the final amount of tested memory.
|
|||
|
//
|
|||
|
|
|||
|
SetCursorPosition(4,15);
|
|||
|
sprintf(String,"%6d",CurrentK);
|
|||
|
FwPrint(String);
|
|||
|
}
|
|||
|
|
|||
|
// TEMPTEMP This test won't work on a secondary cache machine, fix.
|
|||
|
// ExecuteTest((TestRoutine)RomReadMergeWrite,LED_READ_MERGE_WRITE);
|
|||
|
|
|||
|
//
|
|||
|
// Test the rest of devices in the board.
|
|||
|
//
|
|||
|
|
|||
|
FwPrint(ST_TEST_MSG);
|
|||
|
FwPrint(ST_MEMORY_CONTROLLER_MSG);
|
|||
|
if (ExecuteTest((TestRoutine)RomIOCacheTest,LED_IO_CACHE)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Enable interrupts and initialize dispatch table.
|
|||
|
//
|
|||
|
|
|||
|
FwPrint(ST_TEST_MSG);
|
|||
|
FwPrint(ST_INTERRUPT_CONTROLLER_MSG);
|
|||
|
ConnectInterrupts();
|
|||
|
if (ExecuteTest((TestRoutine)InterruptControllerTest,LED_INTERRUPT)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
FwPrint(ST_TEST_MSG);
|
|||
|
FwPrint(ST_KEYBOARD_CONTROLLER_MSG);
|
|||
|
if (ExecuteTest((TestRoutine)InitKeyboardController,LED_KEYBOARD_CTRL)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
KeyboardInitialized=TRUE;
|
|||
|
MoveCursorLeft(3);
|
|||
|
FwPrint(" ");
|
|||
|
MoveCursorLeft(3);
|
|||
|
PutLedDisplay(LED_KEYBOARD_INIT);
|
|||
|
if (Status=InitKeyboard()) {
|
|||
|
FwPrint(ST_ERROR_MSG);
|
|||
|
if (Status == TIME_OUT) {
|
|||
|
FwPrint(ST_KEYBOARD_NOT_PRESENT_MSG);
|
|||
|
}
|
|||
|
if (LoopOnError) {
|
|||
|
PutLedDisplay((LED_LOOP_ERROR << 16) | LED_KEYBOARD_INIT);
|
|||
|
for (;;) {
|
|||
|
InitKeyboard();
|
|||
|
}
|
|||
|
} else {
|
|||
|
if (IgnoreErrors) {
|
|||
|
return;
|
|||
|
} else {
|
|||
|
FwPrint(ST_HANG_MSG);
|
|||
|
PutLedDisplay((LED_BLINK << 16) | LED_KEYBOARD_INIT); // does not return.
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
FwPrint(FW_OK_MSG);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Test the serial port if it's not being used as the output device.
|
|||
|
//
|
|||
|
|
|||
|
if (SerialOutput == FALSE) {
|
|||
|
FwPrint(ST_TEST_MSG);
|
|||
|
FwPrint(ST_SERIAL_LINE_MSG);
|
|||
|
if (ExecuteTest((TestRoutine)RomSerialResetTest,LED_SERIAL_RESET)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
if (ExecuteTest((TestRoutine)RomSerial1RegistersTest,LED_SERIAL1_REG)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
if (ExecuteTest((TestRoutine)RomSerial2RegistersTest,LED_SERIAL2_REG)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
if (ExecuteTest((TestRoutine)RomSerial1LoopBackTest,LED_SERIAL1_LBACK)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
if (ExecuteTest((TestRoutine)RomSerial2LoopBackTest,LED_SERIAL2_LBACK)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
FwPrint(ST_TEST_MSG);
|
|||
|
FwPrint(ST_PARALLEL_PORT_MSG);
|
|||
|
if (ExecuteTest((TestRoutine)RomParallelRegistersTest,LED_PARALLEL_REG)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
#ifndef DUO
|
|||
|
FwPrint(ST_TEST_MSG);
|
|||
|
FwPrint(ST_FLOPPY_MSG);
|
|||
|
if (ExecuteTest((TestRoutine)RomFloppyResetTest,LED_FLOPPY_RESET)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
if (ExecuteTest((TestRoutine)RomFloppyRegistersTest,LED_FLOPPY_REG)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
#endif
|
|||
|
FwPrint(ST_TEST_MSG);
|
|||
|
FwPrint(ST_SCSI_MSG);
|
|||
|
if (ExecuteTest((TestRoutine)RomScsiResetTest,LED_SCSI_RESET)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
if (ExecuteTest((TestRoutine)RomScsiRegistersTest,LED_SCSI_REG)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
FwPrint(ST_TEST_MSG);
|
|||
|
FwPrint(ST_ETHERNET_MSG);
|
|||
|
if (ExecuteTest((TestRoutine)RomSonicResetTest,LED_SONIC_RESET)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
if (ExecuteTest((TestRoutine)RomSonicRegistersTest,LED_SONIC_REG)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Do a loopback test if a valid address was found in the NVRAM.
|
|||
|
//
|
|||
|
|
|||
|
if (ValidEthernetAddress) {
|
|||
|
FwPrint(ST_ETHERNET_ADDRESS_MSG);
|
|||
|
j=0;
|
|||
|
for (i=0;i<6;i++) {
|
|||
|
String[j++]=TranslationTable[StationAddress[i]>>4];
|
|||
|
String[j++]=TranslationTable[StationAddress[i]&0xF];
|
|||
|
}
|
|||
|
String[j]='\0';
|
|||
|
FwPrint(String);
|
|||
|
FwPrint(ST_ETHERNET_LOOPBACK_MSG);
|
|||
|
if (ExecuteTest((TestRoutine)RomSonicLoopBackTest,LED_SONIC_LOOPBACK)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// RomSoundTest();
|
|||
|
|
|||
|
//
|
|||
|
// Invalidate DMA translation table
|
|||
|
//
|
|||
|
|
|||
|
WRITE_REGISTER_ULONG(&DMA_CONTROL->TranslationInvalidate.Long,0);
|
|||
|
|
|||
|
FwPrint(ST_TEST_MSG);
|
|||
|
FwPrint(ST_ISP_MSG);
|
|||
|
if (ExecuteTest((TestRoutine)RomInitISP,LED_ISP)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
FwPrint(ST_TEST_MSG);
|
|||
|
FwPrint(ST_RTC_MSG);
|
|||
|
if (ExecuteTest((TestRoutine)RomRTCTest,LED_RTC)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
FwPrint(FW_CRLF_MSG);
|
|||
|
//
|
|||
|
// Disable Interrupts so that the firmware can be initialized
|
|||
|
//
|
|||
|
|
|||
|
DisableInterrupts();
|
|||
|
}
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
ExecuteTest(
|
|||
|
IN TestRoutine Test,
|
|||
|
IN ULONG LedVal
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine executes the specified test. If the test fails and
|
|||
|
the loop-on-error bit is set it sets the dot in the LED and reexecutes
|
|||
|
the test for ever. If the loop-on-error bit is not set it will display
|
|||
|
an error message and hang blinking the test and subtest number in the LED.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Test - Supplies a pointer to the rutine to execute.
|
|||
|
LedVal - Subtest identifier to be displayed in the LED in case of error.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
if the test passes returns FALSE.
|
|||
|
if the test fails:
|
|||
|
if Normal Mode and not KeyboardInitialized blinks test and subtest number in LED and hangs.
|
|||
|
if Normal Mode and KeyboardInitialized, prompts for keypress and then returns TRUE.
|
|||
|
if LoopOnError mode reexecutes the test indefinitly and hangs.
|
|||
|
if IgnoreErrors mode returns TRUE.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PutLedDisplay(LedVal);
|
|||
|
if (Test()) {
|
|||
|
|
|||
|
//
|
|||
|
// The test failed.
|
|||
|
//
|
|||
|
|
|||
|
FwPrint(ST_ERROR_MSG);
|
|||
|
if (LoopOnError) {
|
|||
|
PutLedDisplay((LED_LOOP_ERROR << 16) | LedVal);
|
|||
|
for (;;) {
|
|||
|
Test();
|
|||
|
}
|
|||
|
} else {
|
|||
|
if (IgnoreErrors) {
|
|||
|
//
|
|||
|
// Invalidate TT and disable interrupts.
|
|||
|
//
|
|||
|
WRITE_REGISTER_ULONG(&DMA_CONTROL->TranslationInvalidate.Long,0);
|
|||
|
DisableInterrupts();
|
|||
|
return TRUE;
|
|||
|
} else {
|
|||
|
FwPrint(ST_HANG_MSG);
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// display ...OK. and move the cursor left 3 chars
|
|||
|
// so that if an error follows it overwrites OK.
|
|||
|
//
|
|||
|
|
|||
|
FwPrint(FW_OK_MSG);
|
|||
|
FwPrint("\x9B""3D");
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
VOID
|
|||
|
RomPutLine(
|
|||
|
IN PCHAR String
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine displays the string in the video monitor or sends
|
|||
|
it to a terminal trough the serial port during selftest.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
String - String to display
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ULONG Count;
|
|||
|
if (DisplayOutput) {
|
|||
|
|
|||
|
//
|
|||
|
// Display message on the video.
|
|||
|
//
|
|||
|
|
|||
|
DisplayWrite(0,String,strlen(String),&Count);
|
|||
|
}
|
|||
|
if (SerialOutput) {
|
|||
|
|
|||
|
//
|
|||
|
// Display message on serial Line.
|
|||
|
//
|
|||
|
|
|||
|
while (*String) {
|
|||
|
SerialBootWrite(*String,COMPORT2_VIRTUAL_BASE);
|
|||
|
String++;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
ULONG
|
|||
|
RomSerialRegistersTest(
|
|||
|
IN ULONG SP_BASE
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine verifies that the Serial port 2 registers can be writen and
|
|||
|
read.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Number of errors found.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ULONG Errors=0;
|
|||
|
|
|||
|
//
|
|||
|
// Test registers
|
|||
|
//
|
|||
|
|
|||
|
WRITE_REGISTER_UCHAR(&((PSP_WRITE_REGISTERS)SP_BASE)->LineControl,0xA5); // sets DLAB
|
|||
|
WRITE_REGISTER_UCHAR(&((PSP_WRITE_REGISTERS)SP_BASE)->TransmitBuffer,0xC); // write DL (lsb) for 9600
|
|||
|
WRITE_REGISTER_UCHAR(&((PSP_WRITE_REGISTERS)SP_BASE)->InterruptEnable,0x0); // write DL (msb) for 9600
|
|||
|
CHECK_UCHAR(&((PSP_READ_REGISTERS)SP_BASE)->ReceiveBuffer,0xC) // check DL (lsb)
|
|||
|
CHECK_UCHAR(&((PSP_READ_REGISTERS)SP_BASE)->InterruptEnable,0x0) // check DL (msb)
|
|||
|
WRITE_REGISTER_UCHAR(&((PSP_WRITE_REGISTERS)SP_BASE)->LineControl,0x3); // Clears DLAB & sets8 bit no parity 1 stop bit
|
|||
|
WRITE_REGISTER_UCHAR(&((PSP_WRITE_REGISTERS)SP_BASE)->InterruptEnable,0x0); // disable interrupts
|
|||
|
WRITE_REGISTER_UCHAR(&((PSP_WRITE_REGISTERS)SP_BASE)->FifoControl,0x0); // disable fifo
|
|||
|
CHECK_UCHAR(&((PSP_READ_REGISTERS)SP_BASE)->InterruptEnable,0x0) // check Int enable
|
|||
|
CHECK_UCHAR(&((PSP_READ_REGISTERS)SP_BASE)->LineControl,0x3)
|
|||
|
return Errors;
|
|||
|
}
|
|||
|
|
|||
|
ULONG
|
|||
|
RomSerialLoopBackTest(
|
|||
|
IN ULONG SP_BASE
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine verifies that the Serial port is operational.
|
|||
|
It performs an internal loopback of the ACE.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
SP_BASE - Supplies the virtual address of the serial port.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Number of Errors found.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ULONG Errors=0;
|
|||
|
ULONG i;
|
|||
|
|
|||
|
//
|
|||
|
// Set loopback mode.
|
|||
|
//
|
|||
|
|
|||
|
WRITE_REGISTER_UCHAR(&((PSP_WRITE_REGISTERS)SP_BASE)->ModemControl,0x18);
|
|||
|
READ_REGISTER_UCHAR(&((PSP_READ_REGISTERS)SP_BASE)->LineStatus); // Clear status
|
|||
|
READ_REGISTER_UCHAR(&((PSP_READ_REGISTERS)SP_BASE)->ReceiveBuffer); // Clear Data
|
|||
|
for (i=0;i<256;i++) {
|
|||
|
WRITE_REGISTER_UCHAR(&((PSP_WRITE_REGISTERS)SP_BASE)->TransmitBuffer,(UCHAR)i); // write to port
|
|||
|
TimerTicks=3;
|
|||
|
while (((READ_REGISTER_UCHAR(&((PSP_READ_REGISTERS)SP_BASE)->LineStatus) & 1) == 0) && TimerTicks) {
|
|||
|
}
|
|||
|
if (TimerTicks) {
|
|||
|
CHECK_UCHAR(&((PSP_READ_REGISTERS)SP_BASE)->ReceiveBuffer,(UCHAR)i) // read and check
|
|||
|
} else {
|
|||
|
Errors++; // Timeout
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// clear loopback mode and enable Interrupt line so it's not floating
|
|||
|
//
|
|||
|
|
|||
|
WRITE_REGISTER_UCHAR(&((PSP_WRITE_REGISTERS)SP_BASE)->ModemControl,0x08);
|
|||
|
return Errors;
|
|||
|
}
|
|||
|
|
|||
|
ULONG
|
|||
|
RomSerialResetTest(
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine verifies that the Serial port has been properly reset.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Number of errors found.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ULONG Errors=0;
|
|||
|
|
|||
|
//
|
|||
|
// Check that was properly reset by checking the reset values.
|
|||
|
//
|
|||
|
|
|||
|
CHECK_UCHAR(&SP1_READ->InterruptEnable, 0)
|
|||
|
CHECK_UCHAR(&SP1_READ->InterruptId, 1)
|
|||
|
CHECK_UCHAR(&SP1_READ->LineControl, 0)
|
|||
|
CHECK_UCHAR(&SP1_READ->ModemControl, 0x8)
|
|||
|
|
|||
|
//
|
|||
|
// Do the same with COM2
|
|||
|
//
|
|||
|
|
|||
|
CHECK_UCHAR(&SP2_READ->InterruptEnable, 0)
|
|||
|
CHECK_UCHAR(&SP2_READ->InterruptId, 1)
|
|||
|
CHECK_UCHAR(&SP2_READ->LineControl, 0)
|
|||
|
CHECK_UCHAR(&SP2_READ->ModemControl, 0x8)
|
|||
|
return Errors;
|
|||
|
}
|
|||
|
|
|||
|
ULONG
|
|||
|
RomSerial1RegistersTest(
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine verifies that the Serial port 1 registers can be writen and
|
|||
|
read.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Returns the number of errors found.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
return RomSerialRegistersTest(COMPORT1_VIRTUAL_BASE);
|
|||
|
}
|
|||
|
|
|||
|
ULONG
|
|||
|
RomSerial2RegistersTest(
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine verifies that the Serial port 1 registers can be writen and
|
|||
|
read.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Returns the number of errors found.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
return RomSerialRegistersTest(COMPORT2_VIRTUAL_BASE);
|
|||
|
}
|
|||
|
|
|||
|
ULONG
|
|||
|
RomSerial1LoopBackTest(
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine verifies that the Serial is operational.
|
|||
|
It performs an internal loopback of the ACE.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Number of Errors found.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
return RomSerialLoopBackTest(COMPORT1_VIRTUAL_BASE);
|
|||
|
}
|
|||
|
|
|||
|
ULONG
|
|||
|
RomSerial2LoopBackTest(
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine verifies that the Serial is operational.
|
|||
|
It performs an internal loopback of the ACE.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Number of Errors found.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
return RomSerialLoopBackTest(COMPORT2_VIRTUAL_BASE);
|
|||
|
}
|
|||
|
|
|||
|
ULONG
|
|||
|
RomParallelRegistersTest(
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine verifies that the Parallel port registers can be writen and
|
|||
|
read.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Number of errors found.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ULONG Errors=0;
|
|||
|
UCHAR DataByte;
|
|||
|
|
|||
|
//
|
|||
|
// Test registers. This only checks the static bits. Note: bit 2 of the
|
|||
|
// status register and bit 5 of the control register are used in the second
|
|||
|
// silicon.
|
|||
|
//
|
|||
|
|
|||
|
DataByte = READ_REGISTER_UCHAR(&PARALLEL_READ->Status);
|
|||
|
if ((DataByte & 0x1) != 0x1) {
|
|||
|
Errors++;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
DataByte = READ_REGISTER_UCHAR(&PARALLEL_READ->Control);
|
|||
|
if ((DataByte & 0xC0) != 0xC0) {
|
|||
|
Errors++;
|
|||
|
}
|
|||
|
|
|||
|
return Errors;
|
|||
|
}
|
|||
|
|
|||
|
#ifndef DUO
|
|||
|
ULONG
|
|||
|
RomScsiRegistersTest(
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine verifies that the NCR 53c94 SCSI controller registers can be writen and
|
|||
|
read.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Number of errors found.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ULONG Errors=0;
|
|||
|
|
|||
|
//
|
|||
|
// Test Registers
|
|||
|
//
|
|||
|
|
|||
|
SCSI_WRITE((PSCSI_REGISTERS)SCSI_VIRTUAL_BASE,TransferCountLow,0xAA);
|
|||
|
SCSI_WRITE((PSCSI_REGISTERS)SCSI_VIRTUAL_BASE,TransferCountHigh,0x55);
|
|||
|
SCSI_WRITE((PSCSI_REGISTERS)SCSI_VIRTUAL_BASE,Command,0x80); // Issue a DMA NOP to load the counter
|
|||
|
if (SCSI_READ((PSCSI_REGISTERS)SCSI_VIRTUAL_BASE,TransferCountLow) != 0xAA) { // check counter
|
|||
|
Errors++;
|
|||
|
}
|
|||
|
if (SCSI_READ((PSCSI_REGISTERS)SCSI_VIRTUAL_BASE,TransferCountHigh) != 0x55) { // check counter
|
|||
|
Errors++;
|
|||
|
}
|
|||
|
SCSI_WRITE((PSCSI_REGISTERS)SCSI_VIRTUAL_BASE,TransferCountLow,0x00);
|
|||
|
SCSI_WRITE((PSCSI_REGISTERS)SCSI_VIRTUAL_BASE,TransferCountHigh,0x00);
|
|||
|
SCSI_WRITE((PSCSI_REGISTERS)SCSI_VIRTUAL_BASE,Command,0x80); // Issue a DMA NOP to load the counter
|
|||
|
if (SCSI_READ((PSCSI_REGISTERS)SCSI_VIRTUAL_BASE,TransferCountLow) != 0x00) { // check counter
|
|||
|
Errors++;
|
|||
|
}
|
|||
|
if (SCSI_READ((PSCSI_REGISTERS)SCSI_VIRTUAL_BASE,TransferCountHigh) != 0x00) { // check counter
|
|||
|
Errors++;
|
|||
|
}
|
|||
|
SCSI_WRITE((PSCSI_REGISTERS)SCSI_VIRTUAL_BASE,Configuration1,0x57);
|
|||
|
SCSI_WRITE((PSCSI_REGISTERS)SCSI_VIRTUAL_BASE,Configuration2,0x58);
|
|||
|
if (SCSI_READ((PSCSI_REGISTERS)SCSI_VIRTUAL_BASE,Configuration1) != 0x57) { // check config1
|
|||
|
Errors++;
|
|||
|
}
|
|||
|
if (SCSI_READ((PSCSI_REGISTERS)SCSI_VIRTUAL_BASE,Configuration2) != 0x58) { // check config2
|
|||
|
Errors++;
|
|||
|
}
|
|||
|
SCSI_WRITE((PSCSI_REGISTERS)SCSI_VIRTUAL_BASE,Configuration1,0x00);
|
|||
|
SCSI_WRITE((PSCSI_REGISTERS)SCSI_VIRTUAL_BASE,Configuration2,0x00);
|
|||
|
return Errors;
|
|||
|
}
|
|||
|
#else
|
|||
|
ULONG
|
|||
|
RomScsiRegistersTest(
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine verifies that the NCR C700 SCSI controller registers can be writen and
|
|||
|
read.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Number of errors found.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ULONG Errors=0;
|
|||
|
ULONG Entry;
|
|||
|
UCHAR ByteLane;
|
|||
|
UCHAR ScsiTestData[8] = {0x55,0xAA,0x11,0x22,0x44,0x88,0xFF,0x00};
|
|||
|
UCHAR ScsiTestParity[8] = {0x8,0x0,0x8,0x8,0x0,0x0,0x8,0x0};
|
|||
|
UCHAR Temp;
|
|||
|
ULONG TempLong;
|
|||
|
//
|
|||
|
// Test SCSI 1 Registers
|
|||
|
//
|
|||
|
|
|||
|
SCSI_WRITE_USHORT((PSIOP_REGISTERS)SCSI1_VIRTUAL_BASE,DSP[0],0x5A0F); // write pattern to DSP pointer
|
|||
|
SCSI_WRITE_UCHAR((PSIOP_REGISTERS)SCSI1_VIRTUAL_BASE,DSPS[0],0xE1); // write pattern to DSPS0 pointer
|
|||
|
SCSI_WRITE_UCHAR((PSIOP_REGISTERS)SCSI1_VIRTUAL_BASE,DSPS[1],0xD2); // write pattern to DSPS0 pointer
|
|||
|
SCSI_WRITE_UCHAR((PSIOP_REGISTERS)SCSI1_VIRTUAL_BASE,DSPS[2],0xB4); // write pattern to DSPS0 pointer
|
|||
|
SCSI_WRITE_UCHAR((PSIOP_REGISTERS)SCSI1_VIRTUAL_BASE,DSPS[3],0x78); // write pattern to DSPS0 pointer
|
|||
|
if ((Temp=SCSI_READ_UCHAR((PSIOP_REGISTERS)SCSI1_VIRTUAL_BASE,DSP[0])) != 0x0F) { // check low 4 register
|
|||
|
FwPrint("\r\nRegister %s Expected %lx received %lx\r\n","DSP[0]",0xf,Temp);
|
|||
|
return 1;
|
|||
|
Errors++;
|
|||
|
}
|
|||
|
if ((Temp=SCSI_READ_UCHAR((PSIOP_REGISTERS)SCSI1_VIRTUAL_BASE,DSP[1])) != 0x5A) { // check low 4 register
|
|||
|
FwPrint("\r\nRegister %s Expected %lx received %lx\r\n","DSP[1]",0x5A,Temp);
|
|||
|
return 1;
|
|||
|
Errors++;
|
|||
|
}
|
|||
|
if ((TempLong=SCSI_READ_ULONG((PSIOP_REGISTERS)SCSI1_VIRTUAL_BASE,DSPS)) != 0x78B4D2E1) { // check low 4 register
|
|||
|
FwPrint("\r\nRegister %s Expected %lx received %lx\r\n","DSPS",0x78B4D2E1,TempLong);
|
|||
|
return 1;
|
|||
|
Errors++;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Test SCSI 2 Registers
|
|||
|
//
|
|||
|
|
|||
|
SCSI_WRITE_USHORT((PSIOP_REGISTERS)SCSI2_VIRTUAL_BASE,DSP[0],0x5A0F); // write pattern to DSP pointer
|
|||
|
SCSI_WRITE_UCHAR((PSIOP_REGISTERS)SCSI2_VIRTUAL_BASE,DSPS[0],0xE1); // write pattern to DSPS0 pointer
|
|||
|
SCSI_WRITE_UCHAR((PSIOP_REGISTERS)SCSI2_VIRTUAL_BASE,DSPS[1],0xD2); // write pattern to DSPS0 pointer
|
|||
|
SCSI_WRITE_UCHAR((PSIOP_REGISTERS)SCSI2_VIRTUAL_BASE,DSPS[2],0xB4); // write pattern to DSPS0 pointer
|
|||
|
SCSI_WRITE_UCHAR((PSIOP_REGISTERS)SCSI2_VIRTUAL_BASE,DSPS[3],0x78); // write pattern to DSPS0 pointer
|
|||
|
if (SCSI_READ_UCHAR((PSIOP_REGISTERS)SCSI2_VIRTUAL_BASE,DSP[0]) != 0x0F) { // check low 4 register
|
|||
|
FwPrint("Reg 22");
|
|||
|
return 1;
|
|||
|
Errors++;
|
|||
|
}
|
|||
|
if (SCSI_READ_UCHAR((PSIOP_REGISTERS)SCSI2_VIRTUAL_BASE,DSP[1]) != 0x5A) { // check low 4 register
|
|||
|
FwPrint("Reg 33");
|
|||
|
Errors++;
|
|||
|
}
|
|||
|
if (SCSI_READ_ULONG((PSIOP_REGISTERS)SCSI2_VIRTUAL_BASE,DSPS) != 0x78B4D2E1) { // check low 4 register
|
|||
|
FwPrint("Reg 44");
|
|||
|
return 1;
|
|||
|
Errors++;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Test SCSI 1 DMA Fifo
|
|||
|
//
|
|||
|
for (ByteLane=0; ByteLane < 4; ByteLane++) {
|
|||
|
//
|
|||
|
// Select ByteLane
|
|||
|
//
|
|||
|
SCSI_WRITE_UCHAR((PSIOP_REGISTERS)SCSI1_VIRTUAL_BASE,CTEST4,4+ByteLane);
|
|||
|
|
|||
|
//
|
|||
|
// Write
|
|||
|
//
|
|||
|
for (Entry=0;Entry<8;Entry++) {
|
|||
|
SCSI_WRITE_UCHAR((PSIOP_REGISTERS)SCSI1_VIRTUAL_BASE,CTEST7,ScsiTestParity[Entry]);
|
|||
|
SCSI_WRITE_UCHAR((PSIOP_REGISTERS)SCSI1_VIRTUAL_BASE,CTEST6,ScsiTestData[Entry]);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Read and check
|
|||
|
//
|
|||
|
for (Entry=0;Entry<8;Entry++) {
|
|||
|
if ((Temp=SCSI_READ_UCHAR((PSIOP_REGISTERS)SCSI1_VIRTUAL_BASE,CTEST6)) != ScsiTestData[Entry]) {
|
|||
|
FwPrint("Reg CTEST6 expected %lx received %lx\r\n", ScsiTestData[Entry], Temp);
|
|||
|
return 1;
|
|||
|
Errors++;
|
|||
|
}
|
|||
|
if (((Temp=SCSI_READ_UCHAR((PSIOP_REGISTERS)SCSI1_VIRTUAL_BASE,CTEST2))&0x8) != ScsiTestParity[Entry]) {
|
|||
|
FwPrint("Reg CTEST2 expected %lx received %lx\r\n", ScsiTestParity[Entry], Temp);
|
|||
|
return 1;
|
|||
|
Errors++;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
SCSI_WRITE_UCHAR((PSIOP_REGISTERS)SCSI1_VIRTUAL_BASE,CTEST4,0);
|
|||
|
|
|||
|
//
|
|||
|
// Test SCSI 2 DMA Fifo
|
|||
|
//
|
|||
|
for (ByteLane=0; ByteLane < 4; ByteLane++) {
|
|||
|
//
|
|||
|
// Select ByteLane
|
|||
|
//
|
|||
|
SCSI_WRITE_UCHAR((PSIOP_REGISTERS)SCSI2_VIRTUAL_BASE,CTEST4,4+ByteLane);
|
|||
|
|
|||
|
//
|
|||
|
// Write
|
|||
|
//
|
|||
|
for (Entry=0;Entry<8;Entry++) {
|
|||
|
SCSI_WRITE_UCHAR((PSIOP_REGISTERS)SCSI2_VIRTUAL_BASE,CTEST7,ScsiTestParity[Entry]);
|
|||
|
SCSI_WRITE_UCHAR((PSIOP_REGISTERS)SCSI2_VIRTUAL_BASE,CTEST6,ScsiTestData[Entry]);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Read and check
|
|||
|
//
|
|||
|
for (Entry=0;Entry<8;Entry++) {
|
|||
|
if ((Temp = SCSI_READ_UCHAR((PSIOP_REGISTERS)SCSI2_VIRTUAL_BASE,CTEST6)) != ScsiTestData[Entry]) {
|
|||
|
FwPrint("Reg2 CTEST6 expected %lx received %lx\r\n", ScsiTestData[Entry], Temp);
|
|||
|
return 1;
|
|||
|
Errors++;
|
|||
|
}
|
|||
|
if (((Temp = SCSI_READ_UCHAR((PSIOP_REGISTERS)SCSI2_VIRTUAL_BASE,CTEST2))&0x8) != ScsiTestParity[Entry]) {
|
|||
|
FwPrint("Reg2 CTEST2 expected %lx received %lx\r\n", ScsiTestParity[Entry], Temp);
|
|||
|
return 1;
|
|||
|
Errors++;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
SCSI_WRITE_UCHAR((PSIOP_REGISTERS)SCSI2_VIRTUAL_BASE,CTEST4,0);
|
|||
|
return Errors;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
#ifndef DUO
|
|||
|
ULONG
|
|||
|
RomFloppyRegistersTest(
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine verifies that the Floppy controller registers can be writen and
|
|||
|
read.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Number of errors found.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ULONG Errors=0;
|
|||
|
|
|||
|
//
|
|||
|
// Test registers
|
|||
|
//
|
|||
|
|
|||
|
WRITE_REGISTER_UCHAR(&FLOPPY_WRITE->DigitalOutput,0xec);
|
|||
|
CHECK_UCHAR(&FLOPPY_READ->DigitalOutput,0xec )
|
|||
|
WRITE_REGISTER_UCHAR(&FLOPPY_WRITE->DigitalOutput,0x7B);
|
|||
|
CHECK_UCHAR(&FLOPPY_READ->DigitalOutput,0x7B )
|
|||
|
WRITE_REGISTER_UCHAR(&FLOPPY_WRITE->DigitalOutput,0x08);
|
|||
|
CHECK_UCHAR(&FLOPPY_READ->DigitalOutput, 0x08)
|
|||
|
return Errors;
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
ULONG
|
|||
|
RomSonicRegistersTest(
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine verifies that the Sonic registers can be writen and
|
|||
|
read. It doesn't test all the accessible registers but all the
|
|||
|
address bits are toggled.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Number of errors found.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ULONG Errors=0;
|
|||
|
PSONIC_REGISTERS SonicBase = (volatile PSONIC_REGISTERS) NET_VIRTUAL_BASE;
|
|||
|
USHORT Tmp;
|
|||
|
//
|
|||
|
// Test registers
|
|||
|
//
|
|||
|
|
|||
|
WRITE_REGISTER_USHORT(&SonicBase->UTDA.Reg,0xAAAA);
|
|||
|
WRITE_REGISTER_USHORT(&SonicBase->CRDA.Reg,0x5555);
|
|||
|
WRITE_REGISTER_USHORT(&SonicBase->RRP.Reg,0x1E1E);
|
|||
|
WRITE_REGISTER_USHORT(&SonicBase->RWP.Reg,0xC33C);
|
|||
|
WRITE_REGISTER_USHORT(&SonicBase->WatchdogTimer0.Reg,0xFFFF);
|
|||
|
WRITE_REGISTER_USHORT(&SonicBase->WatchdogTimer1.Reg,0x0000);
|
|||
|
WRITE_REGISTER_USHORT(&SonicBase->FaeTally.Reg,0xFFFF); // clear counter
|
|||
|
CHECK_USHORT(&SonicBase->UTDA.Reg, 0xAAAA)
|
|||
|
CHECK_USHORT(&SonicBase->CRDA.Reg, 0x5555)
|
|||
|
CHECK_USHORT(&SonicBase->RRP.Reg, 0x1E1E)
|
|||
|
CHECK_USHORT(&SonicBase->RWP.Reg, 0xC33C)
|
|||
|
CHECK_USHORT(&SonicBase->WatchdogTimer0.Reg, 0xFFFF)
|
|||
|
CHECK_USHORT(&SonicBase->WatchdogTimer1.Reg, 0)
|
|||
|
CHECK_USHORT(&SonicBase->FaeTally.Reg,0)
|
|||
|
return Errors;
|
|||
|
}
|
|||
|
|
|||
|
#ifndef DUO
|
|||
|
ULONG
|
|||
|
RomScsiResetTest(
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine verifies that the NCR 53c94 SCSI controller was properly reset.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Number of errors found.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ULONG Errors=0;
|
|||
|
|
|||
|
//
|
|||
|
// Test that SCSI was properly reset
|
|||
|
//
|
|||
|
|
|||
|
if (SCSI_READ((PSCSI_REGISTERS)SCSI_VIRTUAL_BASE,Fifo) != 0) { // check Fifo
|
|||
|
Errors++;
|
|||
|
}
|
|||
|
if (SCSI_READ((PSCSI_REGISTERS)SCSI_VIRTUAL_BASE,FifoFlags) != 0 ) { // check Fifo flags
|
|||
|
Errors++;
|
|||
|
}
|
|||
|
if ((SCSI_READ((PSCSI_REGISTERS)SCSI_VIRTUAL_BASE,ScsiStatus) & 0xF8) != 0) { // check status
|
|||
|
Errors++;
|
|||
|
}
|
|||
|
return Errors;
|
|||
|
}
|
|||
|
#else
|
|||
|
ULONG
|
|||
|
RomScsiResetTest(
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine verifies that the NCR c700 SCSI controller was properly reset.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Number of errors found.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ULONG Errors=0;
|
|||
|
ULONG Temp;
|
|||
|
UCHAR Char;
|
|||
|
USHORT Short;
|
|||
|
//
|
|||
|
// Test that SCSI 1 was properly reset
|
|||
|
//
|
|||
|
|
|||
|
if ((Temp=SCSI_READ_ULONG((PSIOP_REGISTERS)SCSI1_VIRTUAL_BASE,SCNTL0)) != 0xC0) { // check low 4 register
|
|||
|
FwPrint("\r\nRegister %s received %lx\r\n","SCNTL0",Temp);
|
|||
|
Errors++;
|
|||
|
}
|
|||
|
if ((Temp=SCSI_READ_ULONG((PSIOP_REGISTERS)SCSI1_VIRTUAL_BASE,SCID)) != 0x0) { // check next 4 register
|
|||
|
FwPrint("\r\nRegister %s received %lx\r\n","SCID",Temp);
|
|||
|
Errors++;
|
|||
|
}
|
|||
|
if ((Char = SCSI_READ_UCHAR((PSIOP_REGISTERS)SCSI1_VIRTUAL_BASE,CTEST1)) != 0xF0) { // check next register
|
|||
|
FwPrint("\r\nRegister %s received %lx\r\n","CTEST1",Char);
|
|||
|
Errors++;
|
|||
|
}
|
|||
|
//
|
|||
|
// This works on power up only.
|
|||
|
//
|
|||
|
// if ((Short=SCSI_READ_USHORT((PSIOP_REGISTERS)SCSI1_VIRTUAL_BASE,CTEST2)) != 0x21) { // check next 2 register
|
|||
|
// FwPrint("\r\nRegister %s received %lx\r\n","CTEST2",Short);
|
|||
|
// Errors++;
|
|||
|
// }
|
|||
|
|
|||
|
SCSI_READ_UCHAR((PSIOP_REGISTERS)SCSI1_VIRTUAL_BASE,SSTAT0);
|
|||
|
if ((Char=SCSI_READ_UCHAR((PSIOP_REGISTERS)SCSI1_VIRTUAL_BASE,ISTAT)) != 0x4) { // check next register
|
|||
|
FwPrint("\r\nRegister %s received %lx\r\n","ISTAT",Char);
|
|||
|
Errors++;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Test that SCSI 2 was properly reset
|
|||
|
//
|
|||
|
|
|||
|
if ((Temp=SCSI_READ_ULONG((PSIOP_REGISTERS)SCSI2_VIRTUAL_BASE,SCNTL0)) != 0xC0) { // check low 4 register
|
|||
|
FwPrint("\r\nRegister2 %s received %lx\r\n","SCNTL0",Temp);
|
|||
|
Errors++;
|
|||
|
}
|
|||
|
if ((Temp=SCSI_READ_ULONG((PSIOP_REGISTERS)SCSI2_VIRTUAL_BASE,SCID)) != 0x0) { // check next 4 register
|
|||
|
FwPrint("\r\nRegister2 %s received %lx\r\n","SCID",Temp);
|
|||
|
Errors++;
|
|||
|
}
|
|||
|
if ((Char = SCSI_READ_UCHAR((PSIOP_REGISTERS)SCSI2_VIRTUAL_BASE,CTEST1)) != 0xF0) { // check next register
|
|||
|
FwPrint("\r\nRegister2 %s received %lx\r\n","CTEST1",Char);
|
|||
|
Errors++;
|
|||
|
}
|
|||
|
|
|||
|
// if ((Short=SCSI_READ_USHORT((PSIOP_REGISTERS)SCSI2_VIRTUAL_BASE,CTEST2)) != 0x21) { // check next 2 register
|
|||
|
// FwPrint("\r\nRegister2 %s received %lx\r\n","CTEST2",Short);
|
|||
|
// Errors++;
|
|||
|
// }
|
|||
|
|
|||
|
SCSI_READ_UCHAR((PSIOP_REGISTERS)SCSI2_VIRTUAL_BASE,SSTAT0);
|
|||
|
if ((Char=SCSI_READ_UCHAR((PSIOP_REGISTERS)SCSI2_VIRTUAL_BASE,ISTAT)) != 0x4) { // check next register
|
|||
|
FwPrint("\r\nRegister2 %s received %lx\r\n","ISTAT",Char);
|
|||
|
Errors++;
|
|||
|
}
|
|||
|
|
|||
|
return Errors;
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
#ifndef DUO
|
|||
|
ULONG
|
|||
|
RomFloppyResetTest(
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine verifies that the Floppy controller has been properly reset.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Number of errors found.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ULONG Errors=0;
|
|||
|
|
|||
|
//
|
|||
|
// Test that Floppy controller was properly reset
|
|||
|
//
|
|||
|
|
|||
|
CHECK_UCHAR(&FLOPPY_READ->DigitalOutput, 0x8)
|
|||
|
return Errors;
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
ULONG
|
|||
|
RomSonicResetTest(
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine verifies that the Sonic cotroller has been properly reset.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Number of errors found.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ULONG Errors=0;
|
|||
|
PSONIC_REGISTERS SonicBase = (volatile PSONIC_REGISTERS) NET_VIRTUAL_BASE;
|
|||
|
USHORT Tmp;
|
|||
|
//
|
|||
|
// Test that Sonic controller was properly reset
|
|||
|
//
|
|||
|
|
|||
|
CHECK_USHORT(&SonicBase->Command.Reg, 0x94)
|
|||
|
CHECK_USHORT(&SonicBase->TransmitControl.Reg, 0x101) // this line was commented out for duo
|
|||
|
CHECK_USHORT(&SonicBase->InterruptStatus.Reg, 0x0)
|
|||
|
CHECK_USHORT(&SonicBase->CamEnable.Reg, 0x0)
|
|||
|
CHECK_USHORT(&SonicBase->ReceiveSequenceCounter.Reg, 0x0)
|
|||
|
return Errors;
|
|||
|
}
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
ValidNvram(
|
|||
|
OUT PUCHAR StationAddress
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine checks that the Nvram is operational.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
StationAddress - Pointer to struct to fill with the station address found in the
|
|||
|
Nvram if it's there.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if the Nvram contains valid configuration data.
|
|||
|
FALSE Otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ULONG i,Errors=0;
|
|||
|
ULONG CheckSum;
|
|||
|
PUCHAR NVRamReadWrite = (PUCHAR) (NVRAM_PAGE0);
|
|||
|
PUCHAR NVRamProtected = (PUCHAR) (NVRAM_PAGE1);
|
|||
|
PUCHAR NVRamReadOnly = (PUCHAR) (NVRAM_PAGE2);
|
|||
|
|
|||
|
//
|
|||
|
// Check the Station Address
|
|||
|
//
|
|||
|
|
|||
|
CheckSum=0;
|
|||
|
for (i=0;i<6;i++) {
|
|||
|
CheckSum+=NVRamReadOnly[i];
|
|||
|
if (CheckSum >= 256) { // carry
|
|||
|
CheckSum++; // Add the carry
|
|||
|
CheckSum &= 0xFF; // remove it from bit 9
|
|||
|
}
|
|||
|
}
|
|||
|
if ((NVRamReadOnly[7]+CheckSum != 0xFF) || (NVRamReadOnly[6]!=0)) {
|
|||
|
ValidEthernetAddress=FALSE;
|
|||
|
return FALSE;
|
|||
|
} else {
|
|||
|
ValidEthernetAddress=TRUE;
|
|||
|
|
|||
|
//
|
|||
|
// Copy the station address.
|
|||
|
//
|
|||
|
|
|||
|
for (i=0;i<6;i++) {
|
|||
|
StationAddress[i]=NVRamReadOnly[i];
|
|||
|
}
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#ifndef DUO
|
|||
|
ULONG
|
|||
|
RomIOCacheTest(
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine tests that the Jazz mctadr registers can be written and read.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
0 if no errors found
|
|||
|
number of errors otherwise
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ULONG Errors=0,i,Block;
|
|||
|
|
|||
|
//
|
|||
|
// Check the 32 data path between mctadr and r4000 by writting to the
|
|||
|
// byte mask and forcing an invalidate afterwards.
|
|||
|
//
|
|||
|
|
|||
|
for (Block=0;Block<8;Block++) {
|
|||
|
WRITE_REGISTER_ULONG(&DMA_CONTROL->CacheMaintenance.Long,Block<<2); // select cache block zero
|
|||
|
WRITE_REGISTER_ULONG(&DMA_CONTROL->LogicalTag.Long,0x80000001); // set LFN to zero
|
|||
|
// page offsset to zero
|
|||
|
// read from device
|
|||
|
// and validate Tag
|
|||
|
WRITE_REGISTER_ULONG(&DMA_CONTROL->ByteMask.Long,0x0F0F0F0F); // set even words to valid.
|
|||
|
WRITE_REGISTER_ULONG(&DMA_CONTROL->PhysicalTag.Long,1); // set PFN to zero and validate Tag
|
|||
|
|
|||
|
//
|
|||
|
// Write data in the IO cache.
|
|||
|
//
|
|||
|
|
|||
|
for (i=0;i<4;i++) { // ?? 2 because of the bug in the mctadr, should be 4
|
|||
|
WRITE_REGISTER_ULONG(&DMA_CONTROL->CacheMaintenance.Long,(Block<<2)+i);// select line & Bank
|
|||
|
WRITE_REGISTER_ULONG(&DMA_CONTROL->BufferWindowLow.Long,Block+i);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Read from memory (and flush buffers) at phys address zero which should match with the phys tag
|
|||
|
// thus invalidating it and clearing the byte mask.
|
|||
|
//
|
|||
|
|
|||
|
for (i=0;i<2;i++) {
|
|||
|
CHECK_ULONG(0xA0000000+(i<<3),Block+i);
|
|||
|
}
|
|||
|
}
|
|||
|
return Errors;
|
|||
|
}
|
|||
|
#else
|
|||
|
ULONG
|
|||
|
RomIOCacheTest(
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine tests that the Duo mctadr registers can be written and read.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
0 if no errors found
|
|||
|
number of errors otherwise
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ULONG Errors=0,i,Block;
|
|||
|
|
|||
|
//
|
|||
|
// Check the 32 data path between mctadr and r4000 by writting to the
|
|||
|
// byte mask and forcing an invalidate afterwards.
|
|||
|
//
|
|||
|
|
|||
|
for (Block=0;Block<8;Block++) {
|
|||
|
WRITE_REGISTER_ULONG(&DMA_CONTROL->IoCacheLogicalTag[Block].Long,0x80000001); // set LFN to zero
|
|||
|
// page offsset to zero
|
|||
|
// read from device
|
|||
|
// and validate Tag
|
|||
|
WRITE_REGISTER_ULONG(&DMA_CONTROL->IoCacheLowByteMask[Block].Long,0x0F0F0F0F); // set even words to valid.
|
|||
|
WRITE_REGISTER_ULONG(&DMA_CONTROL->IoCacheHighByteMask[Block].Long,0x0F0F0F0F); // set even words to valid.
|
|||
|
WRITE_REGISTER_ULONG(&DMA_CONTROL->IoCachePhysicalTag[Block].Long,1); // set PFN to zero and validate Tag
|
|||
|
|
|||
|
//
|
|||
|
// Write data in the IO cache.
|
|||
|
//
|
|||
|
|
|||
|
for (i=0;i<8;i++) { // for each buffer register
|
|||
|
WRITE_REGISTER_ULONG(&DMA_CONTROL->IoCacheBuffer[Block*8+i],Block+i);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Read from memory (and flush buffers) at phys address zero which should match with the phys tag
|
|||
|
// thus invalidating it and clearing the byte mask.
|
|||
|
//
|
|||
|
|
|||
|
for (i=0;i<8;i++) {
|
|||
|
CHECK_ULONG(0xA0000000+(i<<3),Block+i);
|
|||
|
}
|
|||
|
}
|
|||
|
return Errors;
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
ULONG
|
|||
|
InterruptControllerTest(
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine tests that the mctadr registers can be written and read.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ULONG Errors=0,i=0;
|
|||
|
|
|||
|
TimerTicks=1; // set counter to 1
|
|||
|
|
|||
|
// write a zero for 1msec interval.
|
|||
|
|
|||
|
WRITE_REGISTER_ULONG(&DMA_CONTROL->InterruptInterval.Long,0);
|
|||
|
while (TimerTicks) { // test counter until it's zero
|
|||
|
READ_REGISTER_UCHAR(0xBFC00000); // read from ROM to waste time
|
|||
|
if (i++ == 0x1FFFF) { // if timeout
|
|||
|
Errors++; // return errors
|
|||
|
return Errors;
|
|||
|
}
|
|||
|
}
|
|||
|
return Errors;
|
|||
|
}
|
|||
|
VOID
|
|||
|
RomBeep(
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine makes the speaker beep for a seconf.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PutLedDisplay(LED_BEEP);
|
|||
|
WRITE_REGISTER_UCHAR(&ISP->IntTimer1CommandMode,0xB6);
|
|||
|
WRITE_REGISTER_UCHAR(&ISP->IntTimer1SpeakerTone,0x97); // LSB for 440hz
|
|||
|
WRITE_REGISTER_UCHAR(&ISP->IntTimer1SpeakerTone,0x0A); // MSB for 440Hz
|
|||
|
WRITE_REGISTER_UCHAR(&ISP->NMIStatus,3); // Do notforce NMI just enable the speaker beep!
|
|||
|
while (TimerTicks>500) { // wait until counter reaches 500
|
|||
|
}
|
|||
|
WRITE_REGISTER_UCHAR(&ISP->NMIStatus,0); // Disable the speaker beep.
|
|||
|
}
|
|||
|
|
|||
|
UCHAR
|
|||
|
ReadRTCRegister (
|
|||
|
UCHAR Register
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine reads the specified register of the RTC
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Register - Number of the register to read
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Returns the contents of the RTC register.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
//
|
|||
|
// Write the register number into the NMI register of the ISP
|
|||
|
// and disable NMI
|
|||
|
//
|
|||
|
|
|||
|
WRITE_REGISTER_UCHAR(&ISP->NMIEnable,Register | (1 << 7));
|
|||
|
|
|||
|
//
|
|||
|
// Read the register
|
|||
|
//
|
|||
|
|
|||
|
return READ_REGISTER_UCHAR((PUCHAR)RTC_VIRTUAL_BASE);
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
WriteRTCRegister (
|
|||
|
UCHAR Register,
|
|||
|
UCHAR Value
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine writes the Value to the specified RTC register
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Register - Number of the register to write
|
|||
|
|
|||
|
Value - Value to write to the RTC register.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
//
|
|||
|
// Write the register number into the NMI register of the ISP
|
|||
|
// and disable NMI
|
|||
|
//
|
|||
|
|
|||
|
WRITE_REGISTER_UCHAR(&ISP->NMIEnable,Register | (1 << 7));
|
|||
|
|
|||
|
//
|
|||
|
// Write the register
|
|||
|
//
|
|||
|
|
|||
|
WRITE_REGISTER_UCHAR((PUCHAR)RTC_VIRTUAL_BASE,Value);
|
|||
|
}
|
|||
|
ULONG
|
|||
|
ReadTime(
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine reads the current time in the RTC.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Number of seconds since time zero = Jan 1st 1900 12:00:00PM
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
UCHAR DataByte;
|
|||
|
UCHAR Minutes,Seconds;
|
|||
|
ULONG TotalSeconds;
|
|||
|
|
|||
|
//
|
|||
|
// Check for an Update In Progress
|
|||
|
//
|
|||
|
|
|||
|
do {
|
|||
|
DataByte=ReadRTCRegister(RTC_CONTROL_REGISTERA);
|
|||
|
} while (((PRTC_CONTROL_REGISTER_A)(&DataByte))->UpdateInProgress==1);
|
|||
|
|
|||
|
//
|
|||
|
// Read Time from RTC and compute seconds.
|
|||
|
//
|
|||
|
|
|||
|
Minutes = ReadRTCRegister(RTC_MINUTE); // read minutes
|
|||
|
Seconds = ReadRTCRegister(RTC_SECOND); // read seconds
|
|||
|
TotalSeconds = (Minutes * 60) + Seconds; // compute seconds
|
|||
|
return TotalSeconds;
|
|||
|
}
|
|||
|
|
|||
|
ULONG
|
|||
|
RomRTCTest(
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine checks that the RTC is operating correctly by reading
|
|||
|
the time, waiting for a 1.1 seconds, reading time again and checking
|
|||
|
that the two times differ in 1 or 2 seconds.
|
|||
|
|
|||
|
If the RTC is disabled, this routine enables it and sets the time
|
|||
|
to 12:00:00pm Jan 1st 1900. The RTC is set in Binary count mode, and
|
|||
|
12h time format.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Number of errors found.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
UCHAR DataByte;
|
|||
|
ULONG Time;
|
|||
|
|
|||
|
DataByte = ReadRTCRegister(RTC_CONTROL_REGISTERA);
|
|||
|
if (((PRTC_CONTROL_REGISTER_A)(&DataByte))->TimebaseDivisor != 0x2) { // test DV bits to see if rtc is counting.
|
|||
|
|
|||
|
//
|
|||
|
// Enable counter
|
|||
|
//
|
|||
|
|
|||
|
DataByte = 0;
|
|||
|
((PRTC_CONTROL_REGISTER_A)(&DataByte))->TimebaseDivisor = 2;
|
|||
|
WriteRTCRegister(RTC_CONTROL_REGISTERA, DataByte);
|
|||
|
Time = 0;
|
|||
|
TimerTicks = 600; // set counter to 600
|
|||
|
while (TimerTicks) { // Wait for an update to occur
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Set RTC to 24 hour format and binary mode. Set SET Bit
|
|||
|
//
|
|||
|
|
|||
|
DataByte=0;
|
|||
|
((PRTC_CONTROL_REGISTER_B)(&DataByte))->HoursFormat = 1;
|
|||
|
((PRTC_CONTROL_REGISTER_B)(&DataByte))->DataMode = 1;
|
|||
|
((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 1;
|
|||
|
WriteRTCRegister(RTC_CONTROL_REGISTERB, DataByte);
|
|||
|
|
|||
|
//
|
|||
|
// RTC disabled set date to 1-1-1900 0h:0m:0
|
|||
|
//
|
|||
|
|
|||
|
WriteRTCRegister(RTC_SECOND,0); //
|
|||
|
WriteRTCRegister(RTC_MINUTE,0); // 12:00:00 PM
|
|||
|
WriteRTCRegister(RTC_HOUR,0x12); //
|
|||
|
WriteRTCRegister(RTC_DAY_OF_WEEK,1); //sunday
|
|||
|
WriteRTCRegister(RTC_DAY_OF_MONTH,1); // 1st
|
|||
|
WriteRTCRegister(RTC_MONTH,1); // january
|
|||
|
WriteRTCRegister(RTC_YEAR,0); // 1900
|
|||
|
WriteRTCRegister(RTC_SECOND_ALARM,0xFF); // Turn alarm
|
|||
|
WriteRTCRegister(RTC_MINUTE_ALARM,0xFF); // off
|
|||
|
WriteRTCRegister(RTC_HOUR_ALARM,0xFF); //
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Clear SET bit and put in binary mode
|
|||
|
//
|
|||
|
|
|||
|
DataByte=0;
|
|||
|
((PRTC_CONTROL_REGISTER_B)(&DataByte))->HoursFormat = 1;
|
|||
|
((PRTC_CONTROL_REGISTER_B)(&DataByte))->DataMode = 1;
|
|||
|
WriteRTCRegister(RTC_CONTROL_REGISTERB, DataByte);
|
|||
|
|
|||
|
for (DataByte=0;DataByte<2;DataByte++) { // do it twice in case Hour changes
|
|||
|
Time = ReadTime(); // Read Current time
|
|||
|
TimerTicks=1050; // set timeout to 1.05 seconds
|
|||
|
RomBeep(); // Do a beep in the meantime for 500ms
|
|||
|
while (TimerTicks) { // Wait for an update
|
|||
|
} //
|
|||
|
Time = ReadTime() - Time; // compute elapsed time
|
|||
|
if ((Time == 1) || (Time == 2)) { // 1 or 2 seconds passed
|
|||
|
return 0; // RTC counts properly
|
|||
|
}
|
|||
|
} // if it didn't work even the second time it's screw up.
|
|||
|
return 1;
|
|||
|
}
|
|||
|
ULONG
|
|||
|
RomVideoMemory(
|
|||
|
IN VOID
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine tests the video memory.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Number of errors found.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
ULONG VideoMemoryBaseAddress;
|
|||
|
|
|||
|
#ifdef R3000
|
|||
|
VideoMemoryBaseAddress=VIDEO_MEMORY_PHYSICAL_BASE,
|
|||
|
#else
|
|||
|
VideoMemoryBaseAddress=VIDEO_MEMORY_VIRTUAL_BASE,
|
|||
|
#endif
|
|||
|
WriteVideoMemoryAddressTest(VideoMemoryBaseAddress,
|
|||
|
VIDEO_MEMORY_SIZE
|
|||
|
);
|
|||
|
return CheckVideoMemoryAddressTest(VideoMemoryBaseAddress,
|
|||
|
VIDEO_MEMORY_SIZE
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
ULONG
|
|||
|
RomInitISP (
|
|||
|
VOID
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine initializes the EISA interrupt controller.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Returns the number of errors found.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
UCHAR DataByte;
|
|||
|
|
|||
|
ULONG InterruptLevel;
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the EISA interrupt controller. There are two cascaded
|
|||
|
// interrupt controllers, each of which must initialized with 4 initialize
|
|||
|
// control words.
|
|||
|
//
|
|||
|
|
|||
|
DataByte = 0;
|
|||
|
((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
|
|||
|
((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
|
|||
|
|
|||
|
WRITE_REGISTER_UCHAR(&EISA_CONTROL->Interrupt1ControlPort0,DataByte);
|
|||
|
WRITE_REGISTER_UCHAR(&EISA_CONTROL->Interrupt2ControlPort0,DataByte);
|
|||
|
|
|||
|
//
|
|||
|
// The second intitialization control word sets the iterrupt vector to
|
|||
|
// 0-15.
|
|||
|
//
|
|||
|
|
|||
|
DataByte = 0;
|
|||
|
|
|||
|
WRITE_REGISTER_UCHAR(&EISA_CONTROL->Interrupt1ControlPort1,DataByte);
|
|||
|
|
|||
|
DataByte = 0x08;
|
|||
|
|
|||
|
WRITE_REGISTER_UCHAR(&EISA_CONTROL->Interrupt2ControlPort1,DataByte);
|
|||
|
|
|||
|
//
|
|||
|
// The thrid initialization control word set the controls for slave mode.
|
|||
|
// The master ICW3 uses bit position and the slave ICW3 uses a numberic.
|
|||
|
//
|
|||
|
|
|||
|
DataByte = 1 << SLAVE_IRQL_LEVEL;
|
|||
|
|
|||
|
WRITE_REGISTER_UCHAR(&EISA_CONTROL->Interrupt1ControlPort1,DataByte);
|
|||
|
|
|||
|
DataByte = SLAVE_IRQL_LEVEL;
|
|||
|
|
|||
|
WRITE_REGISTER_UCHAR(&EISA_CONTROL->Interrupt2ControlPort1,DataByte);
|
|||
|
|
|||
|
//
|
|||
|
// The fourth initialization control word is used to specify normal
|
|||
|
// end-of-interrupt mode and not special-fully-nested mode.
|
|||
|
//
|
|||
|
|
|||
|
DataByte = 0;
|
|||
|
((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1;
|
|||
|
|
|||
|
WRITE_REGISTER_UCHAR(&EISA_CONTROL->Interrupt1ControlPort1,DataByte);
|
|||
|
WRITE_REGISTER_UCHAR(&EISA_CONTROL->Interrupt2ControlPort1,DataByte);
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Mask all the interrupts.
|
|||
|
//
|
|||
|
|
|||
|
WRITE_REGISTER_UCHAR(&EISA_CONTROL->Interrupt1ControlPort1,0xFF);
|
|||
|
WRITE_REGISTER_UCHAR(&EISA_CONTROL->Interrupt2ControlPort1,0xFF);
|
|||
|
|
|||
|
//
|
|||
|
// Check that the interrupt level is 7 (i.e. no interrupt is pending)
|
|||
|
//
|
|||
|
#ifndef DUO
|
|||
|
InterruptLevel=READ_REGISTER_UCHAR(&DMA_CONTROL->InterruptAcknowledge);
|
|||
|
InterruptLevel=READ_REGISTER_UCHAR(&DMA_CONTROL->InterruptAcknowledge);
|
|||
|
if (InterruptLevel == 0x07) {
|
|||
|
return 0;
|
|||
|
} else {
|
|||
|
return 1;
|
|||
|
}
|
|||
|
#else
|
|||
|
InterruptLevel=READ_REGISTER_ULONG(&DMA_CONTROL->EisaInterruptAcknowledge);
|
|||
|
InterruptLevel=READ_REGISTER_ULONG(&DMA_CONTROL->EisaInterruptAcknowledge);
|
|||
|
if (InterruptLevel == 0x0) {
|
|||
|
return 0;
|
|||
|
} else {
|
|||
|
FwPrint("\r\nEisa Interrupt level =%lx ",InterruptLevel);
|
|||
|
return 1;
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
FwPrintVersion (
|
|||
|
VOID
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine prints the PROM version.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
FwPrint(ST_ARC_MULTIBOOT_MSG,*(PULONG)(PROM_ENTRY(2)));
|
|||
|
FwPrint(ST_COPYRIGHT_MSG);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
#ifndef DUO
|
|||
|
VOID
|
|||
|
ReportJazzCacheErrorException(
|
|||
|
IN ULONG CacheErr
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine prints cache error / parity information.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
CacheErr - R4000 CacheErr register.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
ULONG ParityDiag[3];
|
|||
|
PULONG ParDiag;
|
|||
|
ULONG IntSrc;
|
|||
|
UCHAR String[128];
|
|||
|
|
|||
|
//
|
|||
|
// Display cache error exception message
|
|||
|
//
|
|||
|
FwPrint(MON_CACHE_ERROR_MSG);
|
|||
|
FwPrint(MON_EXCEPTION_MSG);
|
|||
|
|
|||
|
//
|
|||
|
// Align ParDiag to a double word.
|
|||
|
//
|
|||
|
ParDiag = (PULONG) ((ULONG)(&ParityDiag[1]) & 0xFFFFFFF8);
|
|||
|
|
|||
|
if (((PCACHEERR)(&CacheErr))->EE == 1) {
|
|||
|
//
|
|||
|
// This is a parity error on the Memory or SysAd bus.
|
|||
|
//
|
|||
|
IntSrc = READ_REGISTER_ULONG(&DMA_CONTROL->InterruptSource.Long);
|
|||
|
if (IntSrc & (1 << 8)) {
|
|||
|
//
|
|||
|
// This a parity error in memory.
|
|||
|
// Display MFAR and Parity Diag.
|
|||
|
//
|
|||
|
LoadDoubleWord((ULONG)&DMA_CONTROL->ParityDiagnosticLow.Long,ParDiag);
|
|||
|
sprintf(String,
|
|||
|
MON_MEM_PARITY_FAILED_MSG,
|
|||
|
READ_REGISTER_ULONG(&DMA_CONTROL->MemoryFailedAddress.Long),
|
|||
|
*ParDiag,
|
|||
|
*(ParDiag+1)
|
|||
|
);
|
|||
|
FwPrint(String);
|
|||
|
return;
|
|||
|
} else {
|
|||
|
//
|
|||
|
// The error occurred in the system bus.
|
|||
|
//
|
|||
|
FwPrint(MON_BUS_PARITY_ERROR);
|
|||
|
return;
|
|||
|
}
|
|||
|
} else {
|
|||
|
//
|
|||
|
// Internal cache error.
|
|||
|
//
|
|||
|
sprintf(String,MON_CACHE_ERROR_REG_MSG,CacheErr);
|
|||
|
FwPrint(String);
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
#else
|
|||
|
VOID
|
|||
|
ReportDuoCacheErrorException(
|
|||
|
IN ULONG CacheErr
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine prints cache error / ecc information.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
CacheErr - R4000 CacheErr register.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
UCHAR String[128];
|
|||
|
//
|
|||
|
// Display cache error exception message
|
|||
|
//
|
|||
|
FwPrint(MON_CACHE_ERROR_MSG);
|
|||
|
FwPrint(MON_EXCEPTION_MSG);
|
|||
|
if (READ_REGISTER_ULONG(&DMA_CONTROL->WhoAmI.Long)) {
|
|||
|
FwPrint(MON_PROCESSOR_B_EXCEPTION);
|
|||
|
} else {
|
|||
|
FwPrint(MON_PROCESSOR_A_EXCEPTION);
|
|||
|
}
|
|||
|
if (((PCACHEERR)(&CacheErr))->EE == 1) {
|
|||
|
//
|
|||
|
// The error occurred in the system bus.
|
|||
|
//
|
|||
|
FwPrint(MON_BUS_PARITY_ERROR);
|
|||
|
return;
|
|||
|
} else {
|
|||
|
//
|
|||
|
// Internal cache error.
|
|||
|
//
|
|||
|
sprintf(String,MON_CACHE_ERROR_REG_MSG, CacheErr);
|
|||
|
FwPrint(String);
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
#endif
|