/*++
Copyright (c) 1992 NCR Corporation
Module Name:
ncrlarc.c
Abstract:
Author:
Rick Ulmer
Environment:
Kernel mode only.
Revision History:
--*/
//#include "halp.h"
#include "ki.h"
#include "stdio.h"
#include "ncr.h"
#include "ncrcat.h"
#include "ncrsus.h"
extern PPROCESSOR_BOARD_INFO SUSBoardInfo;
extern ULONG NCRLogicalDyadicProcessorMask;
extern ULONG NCRLogicalQuadProcessorMask;
extern ULONG NCRLogicalNumberToPhysicalMask[];
extern ULONG NCRExistingQuadProcessorMask;
extern ULONG NCRActiveProcessorMask;
extern ULONG NCRLarcPageMask;
#define PASS_LARC_TEST 1
#define LARC_TEST 2
#define LARC_BANK0 4
#define LARC_BANK1 8
#define LARC_8MB 0x80
#define LARC_2MB 0x40
#define LARC_PAGES 8
#define LARC_TIMEOUT 40000 // This is what the UNIX Guys use.
ULONG NCRLarcEnabledPages[8] = {0}; // LARC size by Voyager slot
PCHAR
NCRUnicodeToAnsi(
IN PUNICODE_STRING UnicodeString,
OUT PCHAR AnsiBuffer,
IN ULONG MaxAnsiLength
)
{
PCHAR Dst;
PWSTR Src;
ULONG Length;
Length = UnicodeString->Length / sizeof( WCHAR );
if (Length >= MaxAnsiLength) {
Length = MaxAnsiLength - 1;
}
Src = UnicodeString->Buffer;
Dst = AnsiBuffer;
while (Length--) {
*Dst++ = (UCHAR)*Src++;
}
*Dst = '\0';
return AnsiBuffer;
}
VOID
HalpInitializeLarc (
)
/*++
Routine Description:
Initialize any Larc's that may exist on any Quad processor boards
Arguments:
none.
Return Value:
none.
--*/
{
PLIST_ENTRY ModuleListHead;
PLIST_ENTRY Next;
PLDR_DATA_TABLE_ENTRY DataTableEntry;
CHAR Buffer[256];
UCHAR AnsiBuffer[ 32 ];
ULONG i;
PHYSICAL_ADDRESS kernel_physical;
ULONG base;
UCHAR addr[2];
CAT_CONTROL cat_control;
LONG status;
UCHAR data;
UCHAR enable;
BOOLEAN larc_found = FALSE;
ULONG timeout_count;
LONG pages, page, banks;
DBGMSG(("HalpInitializeLarc: KeLoaderBlock = 0x%x\n",KeLoaderBlock));
//
// Dump the loaded module list
//
if (KeLoaderBlock != NULL) {
ModuleListHead = &KeLoaderBlock->LoadOrderListHead;
} else {
DBGMSG(("HalpInitializeLarc: KeLoaderBlock is NULL returning...\n"));
return;
}
Next = ModuleListHead->Flink;
if (Next != NULL) {
i = 0;
DBGMSG(("HalpInitializeLarc: ModuleListHead = 0x%x\n", ModuleListHead));
DBGMSG(("HalpInitializeLarc: Next = 0x%x\n", Next));
while (Next != ModuleListHead) {
DataTableEntry = CONTAINING_RECORD(Next,
LDR_DATA_TABLE_ENTRY,
InLoadOrderLinks);
sprintf (Buffer, "HalpInitializeLarc: Name: %s Base: 0x%x\n",
NCRUnicodeToAnsi(&DataTableEntry->BaseDllName,AnsiBuffer,sizeof(AnsiBuffer)),
DataTableEntry->DllBase
);
DBGMSG((Buffer));
if (strncmp(AnsiBuffer,"ntoskrnl",8) == 0) {
kernel_physical = MmGetPhysicalAddress(DataTableEntry->DllBase);
DBGMSG(("HalpInitializeLarc: Found kernel at Virtual address 0x%x and Physical Address 0x%x\n",
DataTableEntry->DllBase,
kernel_physical.LowPart));
break;
}
if (i++ == 30) {
DBGMSG(("HalpInitializeLarc: ModuleList too long breaking out\n"));
break;
}
Next = Next->Flink;
DBGMSG(("HalpInitializeLarc: Next = 0x%x\n", Next));
}
}
base = 0xffc00000 & kernel_physical.LowPart; // round down to 4MB boundary
addr[0] = base >> 24;
addr[1] = base >> 16;
//
// Lets check for larc info
//
DBGMSG(("HalpInitializeLarc: Lets look to Quad boards and larc\n"));
for (i = 0; i < SUSBoardInfo->NumberOfBoards; i++ ) {
if (SUSBoardInfo->QuadData[i].Type != QUAD) {
continue;
}
switch (SUSBoardInfo->QuadData[i].Slot) {
case 1:
cat_control.Module = QUAD_BB0;
break;
case 2:
cat_control.Module = QUAD_BB1;
break;
case 3:
cat_control.Module = QUAD_BB2;
break;
case 4:
cat_control.Module = QUAD_BB3;
break;
}
cat_control.Asic = QABC;
//
// get LARC bank info
//
cat_control.Command = READ_SUBADDR;
cat_control.NumberOfBytes = 1;
cat_control.Address = 0x3;
status = HalCatBusIo(&cat_control, &enable);
if (((enable & (LARC_BANK0|LARC_BANK1)) == 0) || (status != CATNOERR)) {
//
// no LARC on this board
//
continue;
}
larc_found = TRUE;
DBGMSG(("HalpInitializeLarc: Found LARC in Slot %d, with Self_test Reg = 0x%x\n",
SUSBoardInfo->QuadData[i].Slot,
enable));
//
// Disable all 4MB pages
//
data = 0;
cat_control.Command = WRITE_SUBADDR;
cat_control.NumberOfBytes = 1;
cat_control.Address = 0x0;
status = HalCatBusIo(&cat_control, &data);
//
// Set new LARC base
//
cat_control.NumberOfBytes = 2;
cat_control.Address = 0x1;
status = HalCatBusIo(&cat_control, addr);
//
// now lets test the LARC
//
enable |= LARC_TEST; // Run LARC test
cat_control.Command = WRITE_SUBADDR;
cat_control.NumberOfBytes = 1;
cat_control.Address = 0x3;
status = HalCatBusIo(&cat_control, &enable);
}
if (!larc_found) {
return;
}
//
// lets wait for all LARC test to complete
//
DBGMSG(("HalpInitializeLarc: Now waiting for LARC self-test to complete.\n"));
for (i = 0; i < SUSBoardInfo->NumberOfBoards; i++ ) {
if (SUSBoardInfo->QuadData[i].Type != QUAD) {
continue;
}
switch (SUSBoardInfo->QuadData[i].Slot) {
case 1:
cat_control.Module = QUAD_BB0;
break;
case 2:
cat_control.Module = QUAD_BB1;
break;
case 3:
cat_control.Module = QUAD_BB2;
break;
case 4:
cat_control.Module = QUAD_BB3;
break;
}
cat_control.Asic = QABC;
cat_control.Command = READ_SUBADDR;
cat_control.NumberOfBytes = 1;
cat_control.Address = 0x3;
timeout_count = 0;
do {
status = HalCatBusIo(&cat_control, &enable);
if (status != CATNOERR) {
return;
}
if ((enable & (LARC_BANK0|LARC_BANK1)) == 0) {
break; // no LARC on this QUAD board
}
} while ((enable & LARC_TEST) && (++timeout_count < LARC_TIMEOUT));
DBGMSG(("HalpInitializeLarc: LARC in slot %d, complete: enable = 0x%x, timeout_count =%d\n",
SUSBoardInfo->QuadData[i].Slot, enable, timeout_count));
}
DBGMSG(("HalpInitializeLarc: All LARCS test complete.....\n"));
//
// Lets enable the LARCS
//
DBGMSG(("HalpInitializeLarc: Now Enabling LARC pages\n"));
for (i = 0; i < SUSBoardInfo->NumberOfBoards; i++ ) {
if (SUSBoardInfo->QuadData[i].Type != QUAD) {
continue;
}
switch (SUSBoardInfo->QuadData[i].Slot) {
case 1:
cat_control.Module = QUAD_BB0;
break;
case 2:
cat_control.Module = QUAD_BB1;
break;
case 3:
cat_control.Module = QUAD_BB2;
break;
case 4:
cat_control.Module = QUAD_BB3;
break;
}
cat_control.Asic = QABC;
cat_control.Command = READ_SUBADDR;
cat_control.NumberOfBytes = 1;
cat_control.Address = 0x3;
status = HalCatBusIo(&cat_control, &enable);
if (((enable & (LARC_BANK0|LARC_BANK1)) == 0) || (status != CATNOERR)) {
//
// no LARC on this board
//
continue;
}
if ((enable & PASS_LARC_TEST) == 0) {
//
// this LARC did not pass self-test
//
continue;
}
if (enable & LARC_BANK0) {
banks = 1;
} else {
banks = 0;
}
if (enable & LARC_BANK1) {
banks += 1;
}
if (enable & LARC_8MB) {
pages = 4 * banks;
} else {
pages = banks;
}
cat_control.Command = READ_SUBADDR;
cat_control.NumberOfBytes = 1;
cat_control.Address = 0x0;
status = HalCatBusIo(&cat_control, &enable);
DBGMSG(("HalpInitializeLarc: banks = %d, pages = %d\n",banks, pages));
NCRLarcEnabledPages[SUSBoardInfo->QuadData[i].Slot-1] = pages;
for (page = 1; pages > 0; page <<= 1, pages--) {
enable |= page;
}
enable &= NCRLarcPageMask; // now apply enable mask
cat_control.Command = WRITE_SUBADDR;
DBGMSG(("HalpInitializeLarc: Slot %d, enable Mask = 0x%x\n",
SUSBoardInfo->QuadData[i].Slot,
enable));
status = HalCatBusIo(&cat_control, &enable);
}
DBGMSG(("HalpInitializeLarc: Done\n"));
}