summaryrefslogblamecommitdiffstats
path: root/private/ntos/nthals/halncr/i386/ncrlarc.c
blob: e486fcdbc613abac25774a9673be4ace4be4d4f7 (plain) (tree)







































































































































































































































































































































































































                                                                                                                
/*++

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"));
}