393 lines
9.6 KiB
C
393 lines
9.6 KiB
C
/*++
|
|
|
|
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"));
|
|
}
|
|
|
|
|
|
|