// ----------------------------------------------------------------------------
// Copyright (c) 1992 Olivetti
//
// File:            eisaini.c
//
// Description:     EISA initialization routines.
// ----------------------------------------------------------------------------
//

#include "fwp.h"
#include "oli2msft.h"
#include "arceisa.h"
#include "inc.h"
#include "string.h"
#include "debug.h"
#include "eisastr.h"


//extern BL_DEVICE_ENTRY_TABLE OmfEntryTable[];

// NOTE: Not used in JAZZ.
//extern ULONG    ErrorWord;                      // POD error flags
//extern ULONG    FlagWord;                       // system flags
extern ULONG    MemorySize;                     // size of memory in Mb

extern PCHAR    MnemonicTable[];

extern ULONG    EisaPoolSize;                   // # bytes really used
extern ULONG    EisaDynMemSize;                 // dynamic memory size (bytes)
extern ULONG    EisaFreeTop;                    // top of free mem
extern ULONG    EisaFreeBytes;                  // free bytes left



// remove the following function prototypes when using common code

PFW_MD
GetFwMd
    (
    VOID
    );

PFW_MD
LinkPhysFwMd
    (
    PFW_MD * pFwMdBase,
    PFW_MD   pFwMd
    );





// ----------------------------------------------------------------------------
//  Declare Function Prototypes
// ----------------------------------------------------------------------------


VOID
EisaIni
    (
    VOID
    );

VOID
EisaGeneralIni
    (
    VOID
    );

BOOLEAN
EisaBusStructIni
    (
    IN ULONG    BusNumber
    );

BOOLEAN
EisaCheckAdapterComponent
    (
    IN  ULONG                     BusNumber,
    OUT PCONFIGURATION_COMPONENT *pEisaComp
    );

BOOLEAN
EisaBusPod
    (
    IN ULONG    BusNumber
    );

BOOLEAN
EisaPortIni
    (
    IN PUCHAR   EisaIoStart
    );

BOOLEAN
EisaIntIni
    (
    IN PUCHAR           EisaIoStart,
    IN PEISA_INT_INFO   pIntInfo
    );

BOOLEAN
EisaDmaIni
    (
    IN PUCHAR           EisaIoStart,
    IN PEISA_DMA_INFO   pDmaInfo
    );

BOOLEAN
EisaBusCfg
    (
    IN PCONFIGURATION_COMPONENT EisaComponent
    );

BOOLEAN
EisaPhysSlotCfg
    (
    IN ULONG    BusNumber,
    IN PCONFIGURATION_COMPONENT Controller,
    IN ULONG    AdapId
    );

BOOLEAN
EisaVirSlotCfg
    (
    IN ULONG    BusNumber,
    IN PCONFIGURATION_COMPONENT Controller
    );

BOOLEAN
EisaSlotCfg
    (
    IN ULONG    BusNumber,
    IN PCONFIGURATION_COMPONENT Controller,
    IN UCHAR    FunctionsNumber
    );

BOOLEAN
EisaSlotCfgMem
    (
    IN ULONG    BusNumber,
    IN ULONG    SlotNumber,
    IN PUCHAR   EisaFuncInfo
    );

BOOLEAN
EisaSlotCfgIrq
    (
    IN PUCHAR           EisaIoStart,
    IN PEISA_INT_INFO   pIntInfo,
    IN PUCHAR           EisaFuncInfo
    );

BOOLEAN
EisaSlotCfgDma
    (
    IN PUCHAR           EisaIoStart,
    IN PEISA_DMA_INFO   pDmaInfo,
    IN PUCHAR           EisaFuncInfo
    );

BOOLEAN
EisaSlotCfgIni
    (
    IN PUCHAR    EisaIoStart,
    IN PUCHAR    EisaFuncInfo,
    OUT PBOOLEAN EnabAdapter
    );

VOID
EisaSlotErrorLog
    (
    IN ULONG            BusNumber,
    IN ULONG            SlotNumber,
    IN EISA_CFG_ERROR   ErrorCode
    );

VOID
EisaPathErrorLog
    (
    IN PCONFIGURATION_COMPONENT Controller,
    IN EISA_CFG_ERROR           ErrorCode
    );

VOID
EisaStrErrorLog
    (
    IN PCHAR            Str,
    IN EISA_CFG_ERROR   ErrorCode
    );

VOID
EisaCheckpointFirstFase
    (
    IN EISA_CHECKPOINT  Chk
    );

BOOLEAN
EisaCheckpointFinalFase
    (
    IN EISA_CHECKPOINT  Chk,
    IN BOOLEAN          Passed
    );

BOOLEAN
EisaReadReadyId
    (
    IN PUCHAR EisaIoStart,
    IN ULONG SlotNumber,
    OUT PULONG AdapId
    );

VOID
EisaReadId
    (
    IN PUCHAR EisaIoStart,
    IN ULONG SlotNumber,
    OUT PULONG AdapId
    );

BOOLEAN
EisaMemIni
    (
    VOID
    );

VOID
EisaDynMemIni
    (
    VOID
    );

PCONFIGURATION_COMPONENT
FwGetChild
    (
    IN PCONFIGURATION_COMPONENT Component OPTIONAL
    );

PCONFIGURATION_COMPONENT
FwGetPeer
    (
    IN PCONFIGURATION_COMPONENT Component
    );

PCONFIGURATION_COMPONENT
FwAddChild
    (
    IN PCONFIGURATION_COMPONENT Component,
    IN PCONFIGURATION_COMPONENT NewComponent,
    IN PVOID ConfigurationData OPTIONAL
    );

PCONFIGURATION_COMPONENT
FwGetComponent
    (
    IN PCHAR Pathname
    );

PCONFIGURATION_COMPONENT
FwGetParent
    (
    IN PCONFIGURATION_COMPONENT Component
    );

VOID
FwStallExecution
    (
    IN ULONG Seconds
    );

ARC_STATUS
AllocateMemoryResources
    (
    IN OUT PFW_MD       pBuffFwMd
    );


// ----------------------------------------------------------------------------
//  Declare General Function Prototypes
// ----------------------------------------------------------------------------

PCHAR
FwToUpperStr
    (
    IN OUT PCHAR s
    );

PCHAR
FwToLowerStr
    (
    IN OUT PCHAR s
    );

PCHAR
FwGetPath
    (
    IN PCONFIGURATION_COMPONENT Component,
    OUT PCHAR String
    );

VOID
FwDelCfgTreeNode
    (
    IN PCONFIGURATION_COMPONENT pComp,
    IN BOOLEAN                  Peer
    );

PCHAR
FwGetMnemonic
    (
    IN PCONFIGURATION_COMPONENT Component
    );

BOOLEAN
FwValidMnem
    (
    IN PCHAR Str
    );

ULONG
Fw2UcharToUlongLSB
    (
    IN PUCHAR String
    );

ULONG
Fw3UcharToUlongLSB
    (
    IN PUCHAR String
    );

ULONG
Fw4UcharToUlongLSB
    (
    IN PUCHAR String
    );

ULONG
Fw4UcharToUlongMSB
    (
    IN PUCHAR String
    );

PCHAR
FwStoreStr
    (
    IN PCHAR Str
    );


// ----------------------------------------------------------------------------
// GLOBAL:      EISA configuration variables
// ----------------------------------------------------------------------------


// EISA buses info

EISA_BUS_INFO EisaBusInfo[ EISA_BUSES ];        // eisa bus info pointers

// descriptor pointers

PFW_MD  LogFwMdBase = NULL;             // starting logical descriptors pointer
PFW_MD  VirFwMdBase = NULL;             // starting virtual descriptors pointer
PFW_MD  pFwMdPool;                      // descriptors pool





// ----------------------------------------------------------------------------
// PROCEDURE:           EisaIni:
//
// DESCRIPTION:         This function does the eisa controller configuration.
//
// ARGUMENTS:           none
//
// RETURN:              none
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:             ErrorWord
//
// NOTES:
// ----------------------------------------------------------------------------
//

VOID
EisaIni
    (
    VOID
    )
{
    // define local variables

    PCONFIGURATION_COMPONENT pEisaComp;         // eisa bus component
    CHAR    EisaMnemonic[MAX_MNEMONIC_LEN +1];  // to hold the eisa path
    ULONG   EisaBus;                            // eisa bus number
    BOOLEAN IniOk;                              // EISA configuration bus status

    PRINTDBG("EisaIni\n\r");                    // DEBUG SUPPORT

    //
    // perform any general initialization
    //

    EisaGeneralIni();

// NOTE: EisaMemIni not used on JAZZ.
//    if ( !EisaMemIni() )
//    {
//        EisaStrErrorLog("EISA Initialization", MemAllocError);
//        return;
//    }

    //
    // initialize and configure the eisa buses (one per loop)
    //

    for ( EisaBus = 0;  EisaBus < EISA_BUSES;  EisaBus++ )
    {
        //
        // display message
        //

        FwPrint(EISA_INIT_MSG, EisaBus);

        //
        // eisa bus structures initialization
        //

        if ( !EisaBusStructIni( EisaBus ))
        {
            EisaStrErrorLog( EISA_BUS_MSG, MemAllocError);
            return;
        }

        //
        // eisa bus hardware test and initialization
        //

        if ( EisaBusInfo[ EisaBus ].Flags.Error = !EisaBusPod( EisaBus ))
        {
//            ErrorWord |= E_HARDWARE_ERROR;
        }

        //
        // check the EISA adapter component
        //

        IniOk = TRUE;
        EisaCheckpointFirstFase( EisaCfg );
        if ( !EisaCheckAdapterComponent( EisaBus, &pEisaComp ))
        {
                IniOk = FALSE;
	}

	//
	// Return if no EISA information available.
	//

	if (pEisaComp == NULL) {
	    return;
	}

        //
        // configure the bus if no hardware errors and configuration jumper not
        // present.
        //

// NOTE: FlagWord is not used in JAZZ.
//        if (!EisaBusInfo[EisaBus].Flags.Error && !(FlagWord & F_CONFIG_JUMPER))
        if (!EisaBusInfo[EisaBus].Flags.Error)
        {
            if ( !EisaBusCfg( pEisaComp ))
            {
                IniOk = FALSE;
            }
        }
        EisaCheckpointFinalFase( EisaCfg, IniOk );

        if ( IniOk != TRUE )
        {
// NOTE: Not used in JAZZ.
//            ErrorWord |= E_CONFIG_ERROR;
        }

        //
        // store the POD initialization status
        //

        EisaBusInfo[ EisaBus ].Flags.IniDone    = 1;
        pEisaComp->Flags.Failed = EisaBusInfo[ EisaBus ].Flags.Error;

        if (IniOk == TRUE) {
            FwPrint(EISA_OK_MSG);
            FwStallExecution(500000);
        }
        FwPrint(EISA_CRLF_MSG);
    }

    //
    // Big Endian initialization
    //

// NOTE: BigEndian is not used on JAZZ.
//    BiEndianIni();

    //
    // EISA dynamic memory initializzation
    //

// NOTE: EisaDynMemIni not used on JAZZ.
//    EisaDynMemIni();

    //
    // OMF initialization:  final phase
    //

// NOTE: EisaOmfIni not used on JAZZ.
//    EisaOmfIni();

    //
    // Write out the hardware id, JAZZ only.  The first page of the EISA
    // I/O control space is actually translated into a page of memory, where
    // the hardware ID is stored.
    //

    *(PUCHAR)(EISA_EXTERNAL_IO_VIRTUAL_BASE + 0x0c80) = (('J' - 'A' + 1) << 2) +
                                                        (('A' - 'A' + 1) >> 3);
    *(PUCHAR)(EISA_EXTERNAL_IO_VIRTUAL_BASE + 0x0c81) = (('A' - 'A' + 1) << 5) +
                                                         ('Z' - 'A' + 1);
    *(PUCHAR)(EISA_EXTERNAL_IO_VIRTUAL_BASE + 0x0c82) = 0;
    *(PUCHAR)(EISA_EXTERNAL_IO_VIRTUAL_BASE + 0x0c83) = 0;

    //
    // all done
    //

    return;
}






// ----------------------------------------------------------------------------
// PROCEDURE:           EisaGeneralIni:
//
// DESCRIPTION:         This function performs general initialization
//                      for the EISA buses.
//
// ARGUMENTS:           none
//
// RETURN:              none
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//

VOID
EisaGeneralIni
    (
    VOID
    )
{
    PRINTDBG("EisaGeneralIni\n\r");             // DEBUG SUPPORT

    //
    // update system parameter block
    //

    SYSTEM_BLOCK->AdapterCount      = 1;

    SYSTEM_BLOCK->Adapter0Type      = EisaAdapter;

    SYSTEM_BLOCK->Adapter0Length    = (ULONG)MaximumEisaRoutine * sizeof(ULONG);

    SYSTEM_BLOCK->Adapter0Vector    = (PVOID)(SYSTEM_BLOCK->VendorVector +
                                              SYSTEM_BLOCK->VendorVectorLength);

    //
    // initialize EISA call back vectors
    //

    SYSTEM_BLOCK->Adapter0Vector
    [ProcessEOIRoutine] = EisaProcessEndOfInterrupt;
//    [ProcessEOIRoutine] = FwpReservedRoutine;

    SYSTEM_BLOCK->Adapter0Vector
    [TestIntRoutine] = EisaTestEisaInterrupt;
//    [TestIntRoutine] = FwpReservedRoutine;

    SYSTEM_BLOCK->Adapter0Vector
//    [RequestDMARoutine] = EisaRequestEisaDmaTransfer;
    [RequestDMARoutine] = FwpReservedRoutine;

    SYSTEM_BLOCK->Adapter0Vector
//    [AbortDMARoutine] = EisaAbortEisaDmaTransfer;
    [AbortDMARoutine] = FwpReservedRoutine;

    SYSTEM_BLOCK->Adapter0Vector
//    [GetDMAStatusRoutine] = EisaGetEisaDmaTransferStatus;
    [GetDMAStatusRoutine] = FwpReservedRoutine;

    SYSTEM_BLOCK->Adapter0Vector
//    [DoLockRoutine] = EisaDoLockedOperation;
    [DoLockRoutine] = FwpReservedRoutine;

    SYSTEM_BLOCK->Adapter0Vector
//    [RequestBusMasterRoutine] = EisaRequestEisaBusMasterTransfer;
    [RequestBusMasterRoutine] = FwpReservedRoutine;

    SYSTEM_BLOCK->Adapter0Vector
//    [ReleaseBusMasterRoutine] = EisaReleaseEisaBusMasterTransfer;
    [ReleaseBusMasterRoutine] = FwpReservedRoutine;

    SYSTEM_BLOCK->Adapter0Vector
//    [RequestCpuAccessToBusRoutine] = EisaRequestCpuAccessToEisaBus;
    [RequestCpuAccessToBusRoutine] = FwpReservedRoutine;

    SYSTEM_BLOCK->Adapter0Vector
//    [ReleaseCpuAccessToBusRoutine] = EisaReleaseCpuAccessToEisaBus;
    [ReleaseCpuAccessToBusRoutine] = FwpReservedRoutine;

    SYSTEM_BLOCK->Adapter0Vector
//    [FlushCacheRoutine] = EisaFlushCache;
    [FlushCacheRoutine] = FwpReservedRoutine;

    SYSTEM_BLOCK->Adapter0Vector
//    [InvalidateCacheRoutine] = EisaInvalidateCache;
    [InvalidateCacheRoutine] = FwpReservedRoutine;

    SYSTEM_BLOCK->Adapter0Vector
    [BeginCriticalSectionRoutine] = EisaBeginCriticalSection;
//    [BeginCriticalSectionRoutine] = FwpReservedRoutine;

    SYSTEM_BLOCK->Adapter0Vector
    [ReservedRoutine] = NULL;

    SYSTEM_BLOCK->Adapter0Vector
    [EndCriticalSectionRoutine] = EisaEndCriticalSection;
//    [EndCriticalSectionRoutine] = FwpReservedRoutine;

    SYSTEM_BLOCK->Adapter0Vector
    [GenerateToneRoutine] = EisaGenerateTone;

    SYSTEM_BLOCK->Adapter0Vector
//    [FlushWriteBuffersRoutine] = EisaFlushWriteBuffers;
    [FlushWriteBuffersRoutine] = FwpReservedRoutine;

    SYSTEM_BLOCK->Adapter0Vector
//    [YieldRoutine] = EisaYield;
    [YieldRoutine] = FwpReservedRoutine;

    SYSTEM_BLOCK->Adapter0Vector
    [StallProcessorRoutine] = FwStallExecution;

    //
    // all done
    //

    return;
}








// ----------------------------------------------------------------------------
// PROCEDURE:           EisaBusStructIni:
//
// DESCRIPTION:         This function builds all the required structures
//                      for the specified EISA bus.
//
// ARGUMENTS:           BusNumber       EISA bus number
//
// RETURN:              TRUE            All done
//                      FALSE           Error
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:               This routine is hardware design dependent.
//
// ----------------------------------------------------------------------------
//

BOOLEAN
EisaBusStructIni
    (
    IN ULONG BusNumber
    )
{

    //
    // define local variables
    //

    PVOID               pInfo;                  // General pointer
    PEISA_BUS_INFO      pBusInfo;               // EISA bus info pointer
    PFW_MD              pIoBusInfo;             // I/O info pointer
    PFW_MD              pMemBusInfo;            // Memory info pointer
    PEISA_SLOTS_INFO    pSlotsInfo;             // Slots info pointer
    PEISA_DMA_INFO      pDmaInfo;               // DMA info pointer
    PEISA_INT_INFO      pIntInfo;               // INT info pointer
    PEISA_PORT_INFO     pPortInfo;              // port info pointer
    ULONG               Index;                  // general index

    PRINTDBG("EisaBusStructIni\n\r");           // DEBUG SUPPORT

    //
    // initialize variables
    //

    pBusInfo = &EisaBusInfo[ BusNumber ];
    pBusInfo->Flags.IniDone = 0;

    //
    // first EISA bus
    //

    if ( BusNumber == 0 )
    {
        //
        // perform any info structure initialization
        //

        if ((pInfo = (PVOID)FwAllocatePool( sizeof( FW_MD ) +
                                            sizeof( FW_MD ) +
                                            sizeof( EISA_SLOTS_INFO ) +
                                            sizeof( EISA_DMA_INFO ) +
                                            sizeof( EISA_INT_INFO ))) == NULL )
        {
            return FALSE;
        }


        //
        // I/O bus info initialization
        //

        pBusInfo->IoBusInfo = pIoBusInfo = (PFW_MD)pInfo;

        // set link and flags

        pIoBusInfo->Link                = NULL;
        pIoBusInfo->Flags.Busy          = 1;
        pIoBusInfo->Counter             = 1;

        // set window size in 4k units

        pIoBusInfo->PhysAddr            = EISA_IO_PHYSICAL_BASE/PAGE_SIZE;
        pIoBusInfo->PagOffs             = 0;
        pIoBusInfo->VirAddr             = (PVOID)EISA_EXTERNAL_IO_VIRTUAL_BASE;
        pIoBusInfo->Size                = 64 * 1024;
        pIoBusInfo->PagNumb             = 64/4;

        pInfo = (PFW_MD)pInfo + 1;


        //
        // memory bus info initialization
        //

        pBusInfo->MemBusInfo = pMemBusInfo      = (PFW_MD)pInfo;

        // set link and flags

        pMemBusInfo->Link               = NULL;
        pMemBusInfo->Flags.Busy         = 0;  // window busy flag
        pMemBusInfo->Counter            = 0;

#ifdef  KPW4010

        // set size of window in 4k units

        pMemBusInfo->PhysAddr           = EISA_MEM_PHYSBASE_KPW4010; // #4kpages
        pMemBusInfo->PagOffs            = 0;
        pMemBusInfo->VirAddr            = (PVOID)EISA_VIR_MEM;
        pMemBusInfo->Size               = 0;                         // 4 Gbytes
        pMemBusInfo->PagNumb            = PAGES_IN_4G;

        //
        // Because the EISA memory space in some designs can reach
        // 4Gbytes of length, it is not possible to map the entire area.
        // The allocation of the TLB entries for this space is done at
        // run time using the general calls to the TLB services.
        //

        pMemBusInfo->u.em.WinRelAddr     = 0;
        pMemBusInfo->u.em.WinRelAddrCtrl = NULL;
        pMemBusInfo->u.em.WinShift       = PAGE_4G_SHIFT;

#else // KPW 4000

        // set size of window in 4k units

        pMemBusInfo->PhysAddr           = EISA_MEMORY_PHYSICAL_BASE/PAGE_SIZE;
        pMemBusInfo->PagOffs            = 0;
        pMemBusInfo->VirAddr            = (PVOID)EISA_MEMORY_VIRTUAL_BASE;
        pMemBusInfo->Size               = PAGE_16M_SIZE;
        pMemBusInfo->PagNumb            = PAGE_16M_SIZE/PAGE_SIZE;

        //
        // Because the EISA memory space in some designs can reach
        // 4Gbytes of length, it is not possible to map the entire area.
        // The allocation of the TLB entries for this space is done at
        // run time using the general calls to the TLB services.
        //

        pMemBusInfo->u.em.WinRelAddr     = 0;
        pMemBusInfo->u.em.WinRelAddrCtrl = (PVOID)EISA_LATCH_VIRTUAL_BASE;
        pMemBusInfo->u.em.WinShift       = PAGE_16M_SHIFT;

#endif

        pInfo = (PFW_MD)pInfo + 1;


        //
        // slot info initialization
        //

        pBusInfo->SlotsInfo = pSlotsInfo        = (PEISA_SLOTS_INFO)pInfo;
        pSlotsInfo->PhysSlots = PHYS_0_SLOTS;
        pSlotsInfo->VirSlots = VIR_0_SLOTS;
        pInfo = (PEISA_SLOTS_INFO)pInfo + 1;


        //
        // DMA info initialization
        //

        pBusInfo->DmaInfo       = pDmaInfo      = (PEISA_DMA_INFO)pInfo;
        pDmaInfo->Flags.IniDone = 0;
        pInfo = (PEISA_DMA_INFO)pInfo + 1;


        //
        // PIC info initialization
        //

        pBusInfo->IntInfo       = pIntInfo      = (PEISA_INT_INFO)pInfo;
        pIntInfo->Flags.IniDone = 0;
        pInfo = (PEISA_INT_INFO)pInfo + 1;


        //
        // port info initialization
        //

        pBusInfo->PortInfo      = pPortInfo     = (PEISA_PORT_INFO)pInfo;
        pPortInfo->Flags.IniDone = 0;

    }
    else
    {
        //
        // invalid bus number
        //

        return FALSE;
    }

    //
    // all done
    //

    return TRUE;
}








// ----------------------------------------------------------------------------
// PROCEDURE:           EisaCheckAdapterComponent:
//
// DESCRIPTION:         This function makes sure that there is an EISA adapter
//                      component with the correct configuration data for the
//                      specified EISA bus number.  The routine uses the
//                      following logic :
//
//                      if !(ARC component present)
//                      {
//                          add ARC component;
//                      }
//                      if (EISA bus component present)
//                      {
//                         if !(configuration data correct)
//                         {
//                              display error message;
//                              delete EISA bus node;
//                              add EISA bus component;
//                              return FALSE;
//                         }
//                      }
//                      else
//                      {
//                          add EISA bus component;
//                      }
//                      return TRUE;
//
// ARGUMENTS:           BusNumber       EISA bus number
//                      pEisaComp       address where to store the EISA
//                                      configuration pointer
//
// RETURN:              FALSE           The configuration tree was incorrect.
//                      TRUE            The configuration tree is correct.
//
// ASSUMPTIONS:         The ARC component is present.
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//

BOOLEAN
EisaCheckAdapterComponent
    (
    IN  ULONG                     BusNumber,
    OUT PCONFIGURATION_COMPONENT *pEisaComp
    )
{
    //
    // define local variables
    //

    PCONFIGURATION_COMPONENT    pComp;
    CONFIGURATION_COMPONENT     Comp;
    EISA_ADAPTER_DETAILS        ConfigData;
    BOOLEAN     CfgOk = TRUE;
    CHAR        EisaMnemonic[MAX_MNEMONIC_LEN +1];
    PVOID       IoStart;
    ULONG       IoSize;
    ULONG       Slots;

    PRINTDBG("EisaCheckAdapterComponent\n\r");          // DEBUG SUPPORT

    //
    // initialize varables
    //

    sprintf( EisaMnemonic, "eisa(%lu)", BusNumber );
    *pEisaComp  = NULL;
    IoStart     = EisaBusInfo[ BusNumber ].IoBusInfo->VirAddr;
    IoSize      = EisaBusInfo[ BusNumber ].SlotsInfo->PhysSlots * 0x1000;
    Slots       = EisaBusInfo[ BusNumber ].SlotsInfo->VirSlots ?
                  EisaBusInfo[ BusNumber ].SlotsInfo->VirSlots + 16 :
                  EisaBusInfo[ BusNumber ].SlotsInfo->PhysSlots;

    //
    // if EISA adapter component is present, check its configuration data
    //

    if ((*pEisaComp = FwGetComponent(EisaMnemonic)) != NULL)
    {
        if ((*pEisaComp)->ConfigurationDataLength !=
                     sizeof(EISA_ADAPTER_DETAILS) ||
             FwGetConfigurationData( (PVOID)&ConfigData, *pEisaComp ) ||
             ConfigData.NumberOfSlots !=  Slots   ||
             ConfigData.IoStart       !=  IoStart ||
             ConfigData.IoSize        !=  IoSize   )
        {
            EisaPathErrorLog( *pEisaComp, CfgIncorrect );
            FwDelCfgTreeNode( *pEisaComp, FALSE );
            *pEisaComp  = NULL;
            CfgOk       = FALSE;
        }
    }

    //
    // add EISA adapter component if not present
    //

    if ( *pEisaComp == NULL )
    {
        // get the root component pointer

        if ((pComp = FwGetChild(NULL)) == NULL) {
            return(FALSE);
        }

        // component structure

        RtlZeroMemory( &Comp, sizeof(CONFIGURATION_COMPONENT));
        Comp.Class                              = AdapterClass;
        Comp.Type                               = EisaAdapter;
        Comp.Version                            = ARC_VERSION;
        Comp.Revision                           = ARC_REVISION;
        Comp.Key                                = BusNumber;
        Comp.ConfigurationDataLength            = sizeof(EISA_ADAPTER_DETAILS);
        Comp.IdentifierLength                   = sizeof("EISA");
        Comp.Identifier                         = "EISA";

        // configuration data structure

        RtlZeroMemory( &ConfigData, sizeof(EISA_ADAPTER_DETAILS));
// NOTE: ConfigDataHeader is not used in JAZZ.
//        ConfigData.ConfigDataHeader.Version     = ARC_VERSION;
//        ConfigData.ConfigDataHeader.Revision    = ARC_REVISION;
//        ConfigData.ConfigDataHeader.Type        = NULL;
//        ConfigData.ConfigDataHeader.Vendor      = NULL;
//        ConfigData.ConfigDataHeader.ProductName = NULL;
//        ConfigData.ConfigDataHeader.SerialNumber = NULL;
        ConfigData.NumberOfSlots                = Slots;
        ConfigData.IoStart                      = IoStart;
        ConfigData.IoSize                       = IoSize;

        *pEisaComp = FwAddChild( pComp, &Comp, (PVOID)&ConfigData );
    }

    //
    // return status
    //

    return CfgOk;
}









// ----------------------------------------------------------------------------
// PROCEDURE:           EisaBusCfg:
//
// DESCRIPTION:         This function configures the slots of the specified
//                      eisa bus.
//
//                      if we detect a "not-ready" board, we have to retry
//                      reading the ID again and report a time-out error if
//                      the ID is still not available after 100 msecs.
//                      (according to the EISA specs, the board should be
//                      ready within 100 msecs after reporting the "not-ready"
//                      status).  However, due to the slow init process of
//                      the ESC-1, we need to go with the following algorithm:
//                      - cfg the physical slots, marking the ones not ready.
//                      - cfg the virtual slots
//                      - go back to cfg the not-ready physical slots.
//                      A time of 2 sec will be given to all these not-ready
//                      slots : 200 loops of 10 msec. This period does not
//                      include configuration time for any slot which now
//                      comes up with a valid ID.
//
// ARGUMENTS:           EisaComponent   EISA component pointer
//
// RETURN:              TRUE            Configuration completed successfully
//                      FALSE           At least one configuration error
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//

BOOLEAN
EisaBusCfg
    (
    IN PCONFIGURATION_COMPONENT EisaComponent
    )
{

    //
    // define local variables
    //

    BOOLEAN     CfgOk = TRUE;                   // starting value: all fine
    ULONG       IdTimeoutFlags = 0;             // eisa controllers in time-out
    USHORT      WaitTimeout=TIMEOUT_UNITS;      // time to wait before aborting
    PCONFIGURATION_COMPONENT FirstController;   // first eisa controller
    PCONFIGURATION_COMPONENT Controller;        // eisa controller to configure
    ULONG       BusNumber;                      // eisa bus number
    ULONG       PhysSlots;                      // eisa physical slots
    ULONG       MaxSlots;                       // eisa last slot
    ULONG       SlotNumber;                     // slot number configured
    PULONG      pSlotCfgMap;                    // slot cfg map pointer
    PUCHAR      EisaIoStart;                    // i/o eisa starting space
    ULONG       AdapId;                         // eisa controller id

    PRINTDBG("EisaBusCfg\n\r");                 // DEBUG SUPPORT

    //
    // initialize same variables using the eisa component structure
    //

    BusNumber   = EisaComponent->Key;
    EisaIoStart = EisaBusInfo[ BusNumber ].IoBusInfo->VirAddr;
    PhysSlots   = EisaBusInfo[ BusNumber ].SlotsInfo->PhysSlots;
    MaxSlots    = EisaBusInfo[ BusNumber ].SlotsInfo->VirSlots + 16;
    pSlotCfgMap = &EisaBusInfo[ BusNumber ].SlotsInfo->SlotCfgMap;
    *pSlotCfgMap    = 0;
    FirstController = FwGetChild(EisaComponent);

    //
    // physical slot initialization : one loop per physical slot
    //

    for (SlotNumber=0; SlotNumber<PhysSlots; SlotNumber++)
    {
        // read eisa controller id

        if (!EisaReadReadyId(EisaIoStart, SlotNumber, &AdapId))
        {
            IdTimeoutFlags |= 1<<SlotNumber;
            continue;
        }

        // find the eisa controller for the specified slot

        for (Controller = FirstController;
             Controller!=NULL  && Controller->Key!=SlotNumber;
             Controller = FwGetPeer(Controller));

        // skip cfg if empty slot; report an error if ARC cfg is missing

        if (Controller==NULL)
        {
            if (AdapId!=NO_ADAP_ID)
            {
                EisaSlotErrorLog( BusNumber, SlotNumber, CfgMissing );
                CfgOk = FALSE;
            }
            continue;
        }

        // one physical slot configuration

        if (!EisaPhysSlotCfg(BusNumber, Controller, AdapId))
        {
            CfgOk = FALSE;
            continue;
        }

        // set the "slot" bit to indicate configuration ok

        *pSlotCfgMap |= 1<<SlotNumber;

        // I/O function structures initialization

// NOTE: EisaOmf is not supported in JAZZ.
//        EisaOmfCheck( BusNumber, Controller, AdapId );

    }



    //
    // virtual slot initialization : one loop per virtual slot
    //

    for (SlotNumber=16; SlotNumber<MaxSlots; SlotNumber++)
    {
        // find the eisa controller for the specified slot

        for (Controller = FirstController;
             Controller!=NULL  && Controller->Key!=SlotNumber;
             Controller = FwGetPeer(Controller));

        // if component not present, skip to next virtual slot

        if (Controller==NULL)
        {
            continue;
        }

        // one virtual slot configuration

        if(!EisaVirSlotCfg(BusNumber, Controller))
        {
            CfgOk = FALSE;
            continue;
        }

        // set the "slot" bit to indicate configuration ok

        *pSlotCfgMap |= 1<<SlotNumber;
    }



    //
    // time-out slot initialization
    //

    while(IdTimeoutFlags && WaitTimeout--)
    {
        for ( SlotNumber = 0;
              IdTimeoutFlags && SlotNumber < PHYS_0_SLOTS;
              SlotNumber++ )
        {
            // check if the slot wasn't ready.

            if ( !(IdTimeoutFlags & 1<<SlotNumber))
            {
                continue;
            }

            // read eisa controller id

            if (!EisaReadReadyId(EisaIoStart, SlotNumber, &AdapId))
            {
                continue;
            }
            IdTimeoutFlags &= ~(1<<SlotNumber);

            // find the eisa controller for the specified slot

            for (Controller = FirstController;
                 Controller!=NULL  && Controller->Key!=SlotNumber;
                 Controller = FwGetPeer(Controller));

            // skip cfg if empty slot; report an error if ARC cfg is missing

            if (Controller==NULL)
            {
                if (AdapId!=NO_ADAP_ID)
                {
                    EisaSlotErrorLog(BusNumber, SlotNumber, CfgMissing);
                    CfgOk = FALSE;
                }
                continue;
            }

            // one physical slot configuration

            if (!EisaPhysSlotCfg(BusNumber, Controller, AdapId))
            {
                CfgOk = FALSE;
                continue;
            }

            // set the "slot" bit to indicate configuration ok

            *pSlotCfgMap |= 1<<SlotNumber;

            // I/O function structures initialization

// NOTE: EisaOmf is not supported in JAZZ.
//            EisaOmfCheck( BusNumber, Controller, AdapId );
        }

        // if there are still some slots in time-out stall execution
        // for 10 msec (10,000 usec).

        if (IdTimeoutFlags)
        {
            FwStallExecution (10000l);
        }
    }

    //
    // if controllers in time-out, display error messages and set the
    // failed bit within the associated "components".
    //

    if (IdTimeoutFlags)
    {
        for ( SlotNumber = 0;  SlotNumber < PHYS_0_SLOTS;  SlotNumber++ )
        {
            if ( IdTimeoutFlags & 1<<SlotNumber )
            {
                // display error message

                EisaSlotErrorLog( BusNumber, SlotNumber, IdTimeout );

                // find the eisa controller for the specified slot

                for (Controller = FirstController;
                     Controller!=NULL  &&  Controller->Key!=SlotNumber;
                     Controller = FwGetPeer(Controller));

                // if component present, set failed bit

                if (Controller != NULL)
                {
                    Controller->Flags.Failed = 1;
                }
            }
        }
        CfgOk = FALSE;
    }

//    //
//    // add a wild omf path name for the physical slots non configurated.
//    //
//
//    for ( SlotNumber = 0;  SlotNumber < PHYS_0_SLOTS;  SlotNumber++ )
//    {
//      if ( !(*pSlotCfgMap & 1<<SlotNumber) )
//      {
//          EisaOtherOmfIni( EisaComponent, SlotNumber );
//      }
//    }

    //
    // return configuration status
    //

    return CfgOk;
}








// ----------------------------------------------------------------------------
// PROCEDURE:           EisaPhysSlotCfg:
//
// DESCRIPTION:         This function configures the specified physical slot.
//
// ARGUMENTS:           BusNumber       EISA bus number
//                      Controller      eisa controller component pointer.
//                      AdapId          Eisa Id read from hardware.
//
//
// RETURN:              FALSE           Error
//                      TRUE            All done
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//

BOOLEAN
EisaPhysSlotCfg
    (
    IN ULONG BusNumber,
    IN PCONFIGURATION_COMPONENT Controller,
    IN ULONG AdapId
    )
{
    //
    // define local variables
    //

    EISA_SLOT_INFO EisaSlotInfo;                // pointer to first eisa info
    EISA_CFG_ERROR ErrMessage = CfgNoErrCode;   // eisa cfg error code

    PRINTDBG("EisaPhysSlotCfg\n\r");            // DEBUG SUPPORT

    //
    // validate physical slot configuration
    //

    if (Controller->Flags.Failed)
    {
        ErrMessage = CfgDeviceFailed;   // device failure
    }

    else if ( !(Controller->ConfigurationDataLength) )
    {
        ErrMessage = CfgMissing;        // eisa configuration missing
    }

    else if (Controller->ConfigurationDataLength < EISA_SLOT_MIN_INFO)
    {
        ErrMessage = CfgIncorrect;      // configuration length incorrect
    }

    else if (FwGetConfigurationDataIndex( (PVOID)&EisaSlotInfo,
                                          Controller,
                                          CONFIGDATAHEADER_SIZE,
                                          EISA_SLOT_INFO_SIZE ))
    {
        ErrMessage = CfgIncorrect;      // invalid component
    }

    else if (EisaSlotInfo.FunctionsNumber * EISA_FUNC_INFO_SIZE +
                EISA_SLOT_MIN_INFO != Controller->ConfigurationDataLength)
    {
        ErrMessage = CfgIncorrect;      // configuration length incorrect
    }

    else if (!(EisaSlotInfo.IdInfo & CFG_UNREADABLE_ID)^(AdapId != NO_ADAP_ID))
    {
        ErrMessage = CfgIdError;        // wrong configuration
    }

    else if (AdapId != NO_ADAP_ID  &&
                AdapId != Fw4UcharToUlongMSB(&EisaSlotInfo.Id1stChar))
    {
        ErrMessage = CfgIdError;        // wrong configuration
    }

    else if ((EisaSlotInfo.IdInfo & CFG_SLOT_MASK) != CFG_SLOT_EXP &&
             (EisaSlotInfo.IdInfo & CFG_SLOT_MASK) != CFG_SLOT_EMB )
    {
        ErrMessage = CfgIncorrect;      // wrong configuration
    }

    //
    // if any error, dispaly error message and set the failed bit
    //

    if (ErrMessage != CfgNoErrCode)
    {
        EisaSlotErrorLog( BusNumber, Controller->Key, ErrMessage );
        Controller->Flags.Failed = 1;
        return FALSE;
    }

    //
    // eisa adapter configuration
    //

    return( EisaSlotCfg( BusNumber,
                         Controller,
                         EisaSlotInfo.FunctionsNumber ));
}






// ----------------------------------------------------------------------------
// PROCEDURE:           EisaVirSlotCfg:
//
// DESCRIPTION:         This function configures the specified virtual slot.
//
// ARGUMENTS:           BusNumber       EISA bus number
//                      Controller      eisa controller component pointer.
//
//
// RETURN:              FALSE           Error
//                      TRUE            All done
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//

BOOLEAN
EisaVirSlotCfg
    (
    IN ULONG BusNumber,
    IN PCONFIGURATION_COMPONENT Controller
    )
{
    //
    // define local variables
    //

    EISA_SLOT_INFO EisaSlotInfo;                // pointer to first eisa info
    EISA_CFG_ERROR ErrMessage = CfgNoErrCode;   // eisa cfg error code

    PRINTDBG("EisaVirSlotCfg\n\r");     // DEBUG SUPPORT

    //
    // validate virtual slot configuration
    //

    if (Controller->Flags.Failed)
    {
        ErrMessage = CfgDeviceFailed;   // device failure
    }

    else if ( !(Controller->ConfigurationDataLength) )
    {
        ErrMessage = CfgMissing;        // configuration missing
    }

    if (Controller->ConfigurationDataLength < EISA_SLOT_MIN_INFO)
    {
        ErrMessage = CfgIncorrect;      // configuration length incorrect
    }

    else if (FwGetConfigurationDataIndex( (PVOID)&EisaSlotInfo,
                                          Controller,
                                          CONFIGDATAHEADER_SIZE,
                                          EISA_SLOT_INFO_SIZE ))
    {
        ErrMessage = CfgIncorrect;      // invalid component
    }

    else if (EisaSlotInfo.FunctionsNumber * EISA_FUNC_INFO_SIZE +
                EISA_SLOT_MIN_INFO != Controller->ConfigurationDataLength)
    {
        ErrMessage = CfgIncorrect;      // configuration length incorrect
    }

    else if ( !(EisaSlotInfo.IdInfo & CFG_UNREADABLE_ID) )
    {
        ErrMessage = CfgIdError;                // wrong configuration
    }

    else if ( (EisaSlotInfo.IdInfo & CFG_SLOT_MASK) != CFG_SLOT_VIR)
    {
        ErrMessage = CfgIncorrect;      // wrong configuration
    }

    //
    // if any error, display error message and set the failed bit
    //

    if (ErrMessage != CfgNoErrCode)
    {
        EisaSlotErrorLog( BusNumber, Controller->Key, ErrMessage );
        Controller->Flags.Failed = 1;
        return FALSE;
    }

    //
    // eisa adapter configuration
    //

    return( EisaSlotCfg( BusNumber,
                         Controller,
                         EisaSlotInfo.FunctionsNumber ));
}





// ----------------------------------------------------------------------------
// PROCEDURE:           EisaSlotCfg:
//
// DESCRIPTION:         This function configures the specified slot.
//
// ARGUMENTS:           BusNumber       EISA bus number
//                      Controller      Controller component pointer
//                      FunctionsNumber Number of function to configure
//
// RETURN:              TRUE            Configuration done
//                      FALSE           Error
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//

BOOLEAN
EisaSlotCfg
    (
    IN ULONG    BusNumber,
    IN PCONFIGURATION_COMPONENT Controller,
    IN UCHAR    FunctionsNumber
    )
{
    //
    // define local variables
    //

    UCHAR       FuncFlags;              // function info flags
    UCHAR       Function;               // current function number
    BOOLEAN     CfgOk       = TRUE;     // local configuration status
    BOOLEAN     EnabAdapter = TRUE;     // adapter enable flag
    PUCHAR      EnabPort;               // used to enable the adapter
    PUCHAR      EisaIoStart;            // Eisa I/O virtual space
    PEISA_DMA_INFO pDmaInfo;            // DMA info pointer
    PEISA_INT_INFO pIntInfo;            // interrupts info pointer
    BOOLEAN     CfgMemOk    = TRUE;     // prevent multiple messages
    BOOLEAN     CfgIrqOk    = TRUE;     //      "       "       "
    BOOLEAN     CfgDmaOk    = TRUE;     //      "       "       "
    BOOLEAN     CfgIniOk    = TRUE;     //      "       "       "
    UCHAR       EisaFuncInfo[ EISA_FUNC_INFO_SIZE ];
    ULONG       EisaFuncIndex;

    PRINTDBG("EisaSlotCfg\n\r");        // DEBUG SUPPORT

    //
    // initialize variables
    //

    EisaIoStart = (PUCHAR)EisaBusInfo[ BusNumber ].IoBusInfo->VirAddr;
    pDmaInfo    = EisaBusInfo[ BusNumber ].DmaInfo;
    pIntInfo    = EisaBusInfo[ BusNumber ].IntInfo;
    EisaFuncIndex = EISA_SLOT_MIN_INFO;

    //
    // one function per loop
    //

    for ( Function = 0;
          Function < FunctionsNumber;
          Function++, EisaFuncIndex += EISA_FUNC_INFO_SIZE )
    {
        //
        // read function info
        //

        FwGetConfigurationDataIndex( (PVOID)EisaFuncInfo,
                                     Controller,
                                     EisaFuncIndex,
                                     EISA_FUNC_INFO_SIZE );
        //
        // check if configuration complete, exit if not.
        //

        if ( EisaFuncInfo[ CFG_SLOT_INFO_OFS ] & CFG_INCOMPLETE )
        {
            EisaSlotErrorLog( BusNumber, Controller->Key, CfgIncomplete );
            CfgOk = FALSE;
            break;
        }

        // update eisa function flags

        FuncFlags = EisaFuncInfo[ CFG_FN_INFO_OFS ];

        // skip if free form function

        if ( FuncFlags & CFG_FREE_FORM )
        {
            continue;
        }

        //
        // check if there is any memory entry
        //

// NOTE: Eisa memory not supported on JAZZ.
//        if ( FuncFlags & CFG_MEM_ENTRY )
//        {
//            if ( !EisaSlotCfgMem( BusNumber, Controller->Key, EisaFuncInfo ) &&
//                 CfgMemOk )
//            {
//                EisaSlotErrorLog( BusNumber, Controller->Key, CfgMemError );
//                CfgOk = CfgMemOk = FALSE;
//            }
//        }


        //
        // check if there is any interrupt entry
        //

        if ( FuncFlags & CFG_IRQ_ENTRY )
        {
            if (!EisaSlotCfgIrq( EisaIoStart, pIntInfo, EisaFuncInfo ) &&
                 CfgIrqOk )
            {
                EisaSlotErrorLog( BusNumber, Controller->Key, CfgIrqError );
                CfgOk = CfgIrqOk = FALSE;
            }
        }


        //
        // check if there is any DMA entry
        //

        if ( FuncFlags & CFG_DMA_ENTRY )
        {
            if ( !EisaSlotCfgDma( EisaIoStart, pDmaInfo, EisaFuncInfo ) &&
                 CfgDmaOk )
            {
                EisaSlotErrorLog( BusNumber, Controller->Key, CfgDmaError );
                CfgOk = CfgDmaOk = FALSE;
            }
        }


        //
        // check if there is any port init entry
        //

        if ( FuncFlags & CFG_INI_ENTRY )
        {
            if ( !EisaSlotCfgIni( EisaIoStart, EisaFuncInfo, &EnabAdapter ) &&
                 CfgIniOk )
            {
                EisaSlotErrorLog( BusNumber, Controller->Key, CfgIniError );
                CfgOk = CfgIniOk = FALSE;
            }
        }
    }

    //
    // if all fine, enable the adapter
    //

    if (CfgOk && EnabAdapter)
    {
        EnabPort=EisaIoStart+ Controller->Key*0x1000 +EXPANSION_BOARD_CTRL_BITS;
        EisaOutUchar(EnabPort, EisaInUchar(EnabPort) | 0x01);
    }

    //
    // return status of configuration process
    //

    return CfgOk;
}






// ----------------------------------------------------------------------------
// PROCEDURE:           EisaSlotCfgMem:
//
// DESCRIPTION:         This function configures the eisa memory registers
//                      based on info from NVRAM.
//
// ARGUMENTS:           BusNumber       EISA bus number.
//                      SlotNumber      EISA slot number.
//                      EisaFuncInfo    Function info pointer.
//
// RETURN:              TRUE            All done
//                      FALSE           Error
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//

// NOTE: Eisa memory not supported on JAZZ.
#if 0

BOOLEAN
EisaSlotCfgMem
    (
    IN ULONG  BusNumber,
    IN ULONG  SlotNumber,
    IN PUCHAR EisaFuncInfo
    )
{
    //
    // define local variables
    //

    BOOLEAN     CfgOk = TRUE;           // local configuration status
    PUCHAR      MemBlock;               // start of DMA data buffer
    USHORT      Index = 0;              // index within the memory block
    PFW_MD      pFwMd;                  // memory decriptor pointer
    ULONG       Addr;                   // address in 256 units
    ULONG       Size;                   // size in 1k units
    ULONG       WinSize, WinOffs;       // EISA windows characteristic
    PFW_MD      pMemInfo;               // EISA memory address space info

    PRINTDBG("EisaSlotCfgMem\n\r");     // DEBUG SUPPORT

    //
    // initialize variables
    //

    pMemInfo = EisaBusInfo[ BusNumber ].MemBusInfo;
    MemBlock = &EisaFuncInfo[ CFG_MEM_BLK_OFS ];

    //
    // one loop per each memory entry
    //

    do
    {
        //
        // get a memory descriptor
        //

        if ( (pFwMd = GetFwMd()) == NULL )
        {
            EisaSlotErrorLog( BusNumber, SlotNumber, MemAllocError);
            return FALSE;
        }

        //
        // memory block start and length
        //

        Addr = Fw3UcharToUlongLSB( &MemBlock[Index + 2] );
        Size = Fw2UcharToUlongLSB( &MemBlock[Index + 5] );

        pFwMd->VirAddr  = NULL;
        pFwMd->PhysAddr = Addr >> 4;
        pFwMd->PagOffs  = (Addr << 8) & (PAGE_SIZE - 1);
        pFwMd->Size     = Size ? Size << 10 : 64*1024*1024 ;
        pFwMd->PagNumb  = (pFwMd->PagOffs + Size + PAGE_SIZE - 1) >> PAGE_SHIFT;
        pFwMd->Cache    = FALSE;
        pFwMd->u.m.BusNumber  = BusNumber;
        pFwMd->u.m.SlotNumber = SlotNumber;
        pFwMd->u.m.Type       = MemBlock[ Index ] & CFG_MEM_TYPE;

        //
        // check if the memory size fits within the EISA window
        //

        if ( pMemInfo->u.em.WinShift != PAGE_4G_SHIFT )
        {
            // window size < 4 Gbytes

            WinSize  = 1 << pMemInfo->u.em.WinShift;
            WinOffs  = (Addr << 8) & (WinSize - 1);
            if ( WinSize - WinOffs < pFwMd->Size )
            {
                ReleaseFwMd( &pMemInfo->Link, pFwMd );
                CfgOk = FALSE;
                continue;
            }
        }

        //
        // link the memory descriptor
        //

        if ( LinkPhysFwMd( &pMemInfo->Link, pFwMd ) == NULL )
        {
            ReleaseFwMd( &pMemInfo->Link, pFwMd );
            CfgOk = FALSE;
            continue;
        }
    }
    while ((MemBlock[Index]&CFG_MORE_ENTRY) && ((Index+=7)<CFG_MEM_BLK_LEN));

    //
    // check final index
    //

    if ( !(Index < CFG_MEM_BLK_LEN) )
    {
        CfgOk=FALSE;
    }

    //
    // return configuration status
    //

    return CfgOk;
}
#endif // 0




// ----------------------------------------------------------------------------
// PROCEDURE:           EisaSlotCfgIrq:
//
// DESCRIPTION:         This function configures the interrupt registers
//                      based on info from NVRAM.
//
// ARGUMENTS:           EisaIoStart     EISA I/O virtual address
//                      pIntInfo        interrupt info pointer
//                      EisaFuncInfo    function info pointer.
//
// RETURN:              TRUE            All done
//                      FALSE           Error
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//

BOOLEAN
EisaSlotCfgIrq
    (
    IN PUCHAR           EisaIoStart,
    IN PEISA_INT_INFO   pIntInfo,
    IN PUCHAR           EisaFuncInfo
    )
{
    //
    // define local variables
    //

    BOOLEAN     CfgOk   = TRUE;         // local configuration status
    PUCHAR      IrqBlock;               // start of IRQ data buffer
    USHORT      Index   = 0;            // index within the IRQ block
    USHORT      IrqBit;                 // 0x1=IRQ0... 0x8000=IRQ15
    UCHAR       Register;               // used to update the registers

    PRINTDBG("EisaSlotCfgIrq\n\r");     // DEBUG SUPPORT

    //
    // initialize variables
    //

    IrqBlock = &EisaFuncInfo[ CFG_IRQ_BLK_OFS ];

    //
    // one loop per each IRQ entries
    //

    do
    {
        IrqBit = 1 << ( IrqBlock[ Index ] & CFG_IRQ_MASK ); // compute IRQ bit

        //
        // check shareable and edge/level trigger mode
        //

        if ( pIntInfo->IrqPresent & IrqBit )
        {
            //
            // IRQ already used: check if it is shareabe
            //

            if ( !(pIntInfo->IrqShareable & IrqBit) )
            {
                CfgOk = FALSE;
                continue;
            }
            else if ( !(IrqBlock[Index] & CFG_IRQ_SHARE) )
            {
                CfgOk = FALSE;
                continue;
            }

            //
            // IRQ is shareable: check if the levels are compatible
            //

            else if (  (pIntInfo->IrqLevel & IrqBit) &&
                      !(IrqBlock[Index] & CFG_IRQ_LEVEL)  )
            {
                CfgOk=FALSE;
                continue;
            }
            else if ( !(pIntInfo->IrqLevel & IrqBit) &&
                       (IrqBlock[Index] & CFG_IRQ_LEVEL)  )
            {
                CfgOk=FALSE;
                continue;
            }
        }
        else
        {
            //
            // new IRQ: check if the IRQ 0, 1, 2, 8 and 13 are configurated
            //          for edge triggered.
            //

            switch(IrqBit)
            {
                case (0x0001):  // IRQ 0        only edge triggered
                case (0x0002):  // IRQ 1         "    "    "
                case (0x0004):  // IRQ 2         "    "    "
                case (0x0100):  // IRQ 8         "    "    "
                case (0x2000):  // IRQ 13        "    "    "

                    if (IrqBlock[Index] & CFG_IRQ_LEVEL)
                    {
                        CfgOk=FALSE;
                        continue;
                    }
                    break;

                default:
                    break;
            }
        }

        //
        // set the present bit and update sharable and edge/level
        // triggered variables
        //

        pIntInfo->IrqPresent |= IrqBit;

        if (IrqBlock[Index] & CFG_IRQ_SHARE)
        {
            pIntInfo->IrqShareable |= IrqBit;
        }

        if (IrqBlock[Index] & CFG_IRQ_LEVEL)
        {
            pIntInfo->IrqLevel |= IrqBit;
        }
    }
    while ((IrqBlock[Index]&CFG_MORE_ENTRY) && ((Index+=2)<CFG_IRQ_BLK_LEN));

    //
    // check final index
    //

    if ( !( Index < CFG_IRQ_BLK_LEN ) )
    {
        CfgOk=FALSE;
    }

    //
    // initialize ELCR registers with new values.
    //

    Register  = EisaInUchar(EisaIoStart + PIC1_ELCR);
    Register &= ~(pIntInfo->IrqPresent);
    Register |=   pIntInfo->IrqLevel;
    EisaOutUchar(EisaIoStart + PIC1_ELCR, Register);

    Register = EisaInUchar(EisaIoStart + PIC2_ELCR);
    Register &= ~(pIntInfo->IrqPresent >> BITSXBYTE);
    Register |=   pIntInfo->IrqLevel >> BITSXBYTE;
    EisaOutUchar(EisaIoStart + PIC2_ELCR, Register);

    //
    // return configuration status
    //

    return CfgOk;
}







// ----------------------------------------------------------------------------
// PROCEDURE:           EisaSlotCfgDma:
//
// DESCRIPTION:         This function configures the DMA registers
//                      based on info from NVRAM.
//
// ARGUMENTS:           EisaIoStart     EISA I/O virtual address
//                      pDmaInfo        DMA info pointer
//                      EisaFuncInfo    function info pointer.
//
// RETURN:              TRUE            All done
//                      FALSE           Error
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//

BOOLEAN
EisaSlotCfgDma
    (
    IN PUCHAR           EisaIoStart,
    IN PEISA_DMA_INFO   pDmaInfo,
    IN PUCHAR           EisaFuncInfo
    )
{
    //
    // define local variables
    //

    BOOLEAN CfgOk=TRUE;                 // local configuration status
    PUCHAR DmaBlock;                    // start of DMA data buffer
    USHORT Index=0;                     // index within the DMA block
    UCHAR DmaNumber;                    // DMA under configuration
    UCHAR Register;                     // used to update the registers

    PRINTDBG("EisaSlotCfgDma\n\r");     // DEBUG SUPPORT

    //
    // initialize variables
    //

    DmaBlock = &EisaFuncInfo[ CFG_DMA_BLK_OFS ];

    //
    // one loop per each DMA entry
    //

    do
    {
        //
        // skip if shareable. device drivers should init DMA, not ROM
        //

        // NOTE: the following code has been removed because all the
        //       EISA cards that share the same DMA channel have the
        //       same value in this register.  This is guaranteed by
        //       the configuration utility.

        //if ( DmaBlock[Index] & CFG_DMA_SHARED )
        //{
        //    continue;
        //}

        //
        // Program the specified DMA channel using the new info.
        //

        DmaNumber = DmaBlock[Index] & CFG_DMA_MASK;

        // keep the "stop register" and "T-C" bits

        Register  = pDmaInfo->DmaExtReg[ DmaNumber ] & ~CFG_DMA_CFG_MASK;

        // use the new timing and bit I/O selection

        Register |= DmaBlock[Index+1] & CFG_DMA_CFG_MASK;

        // update the register

        if (DmaNumber < 4)
        {
            EisaOutUchar(EisaIoStart + DMA_EXTMODE03, Register);
        }
        else
        {
            EisaOutUchar(EisaIoStart + DMA_EXTMODE47, Register);
        }

        // This register value is used to validate the DMA requestes
        // (see the "EisaRequestEisaDmaTransfer" function).
        // The DMA channels used by more than one card have always the
        // same value ( check with the configuration guys ).

        pDmaInfo->DmaExtReg[ DmaNumber ] = Register;

    }
    while ((DmaBlock[Index]&CFG_MORE_ENTRY) && ((Index+=2)<CFG_DMA_BLK_LEN));

    //
    // check final index
    //

    if ( !(Index < CFG_DMA_BLK_LEN) )
    {
        CfgOk=FALSE;
    }

    //
    // return configuration status
    //

    return CfgOk;
}




// ----------------------------------------------------------------------------
// PROCEDURE:           EisaSlotCfgIni:
//
// DESCRIPTION:         This function configures the I/O port registers
//                      based on info from NVRAM.
//
// ARGUMENTS:           EisaIoStart     Starting eisa I/O area.
//                      EisaFuncInfo    Function info pointer.
//                      EnabAdapter     Enable adapter flag pointer.
//
// RETURN:              TRUE            All done
//                      FALSE           Error
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//

BOOLEAN
EisaSlotCfgIni
    (
    IN PUCHAR    EisaIoStart,
    IN PUCHAR    EisaFuncInfo,
    OUT PBOOLEAN EnabAdapter
    )
{
    //
    // define local variables
    //

    BOOLEAN CfgOk = TRUE;               // local configuration status
    PUCHAR IniBlock;                    // start of init data buffer
    USHORT Index = 0;                   // index within the init block
    USHORT Next = 0;                    // index within the entry
    USHORT IoPort;                      // I/O address port
    UCHAR ByteValue;                    // used to init the registers
    UCHAR ByteMask;                     //
    USHORT ShortValue;                  // used to init the registers
    USHORT ShortMask;                   //
    ULONG WordValue;                    // used to init the registers
    ULONG WordMask;                     //

    PRINTDBG("EisaSlotCfgIni\n\r");     // DEBUG SUPPORT

    // initialize variables

    IniBlock = &EisaFuncInfo[CFG_INI_BLK_OFS];

    //
    // one loop per each init entries
    //

    do
    {
        // load the i/o address port

        Next = 1;
        IoPort  = IniBlock[Index + Next++];
        IoPort |= IniBlock[Index + Next++] << BITSXBYTE;

        switch(IniBlock[Index] & CFG_INI_MASK)
        {
            //
            // 8-bit I/O access
            //

            case(CFG_INI_BYTE):

                ByteValue = IniBlock[Index + Next++];

                if (IniBlock[Index] & CFG_INI_PMASK)    // use the mask
                {
                    ByteMask   = IniBlock[Index + Next++];
                    ByteValue |= READ_REGISTER_UCHAR(EisaIoStart+IoPort) & ByteMask;
                    EISA_IO_DELAY;
                }

                if ((IoPort & 0x0FFF) == EXPANSION_BOARD_CTRL_BITS)
                {
                    *EnabAdapter=FALSE;
                }
                WRITE_REGISTER_UCHAR(EisaIoStart+IoPort, ByteValue);
                EISA_IO_DELAY;
                break;

            //
            // 16-bit I/O access
            //

            case(CFG_INI_HWORD):

                ShortValue  = IniBlock[Index + Next++];
                ShortValue |= IniBlock[Index + Next++] << BITSXBYTE;

                if (IniBlock[Index] & CFG_INI_PMASK)    // use the mask
                {
                    ShortMask   = IniBlock[Index + Next++];
                    ShortMask  |= IniBlock[Index + Next++] << BITSXBYTE;
                    ShortValue |= READ_REGISTER_USHORT(EisaIoStart + IoPort) &
                                        ShortMask;
                    EISA_IO_DELAY;
                }

                WRITE_REGISTER_USHORT(EisaIoStart + IoPort, ShortValue);
                EISA_IO_DELAY;
                break;

            //
            // 32-bit I/O access
            //

            case(CFG_INI_WORD):

                WordValue = Fw4UcharToUlongLSB( &IniBlock[Index + Next] );
                Next += 4;

                if (IniBlock[Index]&CFG_INI_PMASK)      // use the mask
                {
                    WordMask   = Fw4UcharToUlongLSB( &IniBlock[Index + Next] );
                    Next += 4;
                    WordValue |= READ_REGISTER_ULONG(EisaIoStart + IoPort) &
                                        WordMask;
                    EISA_IO_DELAY;
                }

                WRITE_REGISTER_ULONG(EisaIoStart + IoPort, WordValue);
                EISA_IO_DELAY;
                break;

            //
            // error
            //

            default:
                CfgOk=FALSE;
                break;
        }
    }
    while ((IniBlock[Index]&CFG_MORE_ENTRY) && ((Index+=Next)<CFG_INI_BLK_LEN));

    //
    // check final index
    //

    if ( !(Index < CFG_INI_BLK_LEN) )
    {
        CfgOk=FALSE;
    }

    //
    // return configuration status
    //

    return CfgOk;
}







// ----------------------------------------------------------------------------
// PROCEDURE:           EisaSlotErrorLog:
//
// DESCRIPTION:         This function displays the corresponding eisa
//                      error message.
//
// ARGUMENTS:           BusNumber               BusNumber (not used)
//                      SlotNumber              Slot in error
//                      ErrorCode               Error number.
//
// RETURN:              none
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//

VOID
EisaSlotErrorLog
    (
    IN ULONG            BusNumber,
    IN ULONG            SlotNumber,
    IN EISA_CFG_ERROR   ErrorCode
    )
{
    PRINTDBG("EisaSlotErrorLog\n\r");   // DEBUG SUPPORT

    // display the error message

    FwPrint( EISA_ERROR_SLOT_MSG, SlotNumber, EisaCfgMessages[ErrorCode] );
    FwMoveCursorToColumn( 37 );
    FwPrint( EISA_ERROR1_MSG );
    FwStallExecution(1500000);

    // all done

    return;
}







// ----------------------------------------------------------------------------
// PROCEDURE:           EisaPathErrorLog:
//
// DESCRIPTION:         This function displays the corresponding eisa
//                      error message.
//
// ARGUMENTS:           Component               Component in error.
//                      ErrorCode               Error number.
//
// RETURN:              none
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//

VOID
EisaPathErrorLog
    (
    IN PCONFIGURATION_COMPONENT Controller,
    IN EISA_CFG_ERROR           ErrorCode
    )
{
    CHAR        Path[ MAX_DEVICE_PATH_LEN +1 ];

    PRINTDBG("EisaPathErrorLog\n\r");           // DEBUG SUPPORT

    EisaStrErrorLog( FwGetPath( Controller, Path ), ErrorCode );

    return;
}







// ----------------------------------------------------------------------------
// PROCEDURE:           EisaStrErrorLog:
//
// DESCRIPTION:         This function displays the corresponding eisa
//                      error message.
//
// ARGUMENTS:           Str                     String Message
//                      ErrorCode               Error number.
//
// RETURN:              none
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//

VOID
EisaStrErrorLog
    (
    IN PCHAR            Str,
    IN EISA_CFG_ERROR   ErrorCode
    )
{
    PRINTDBG("EisaStrErrorLog\n\r");    // DEBUG SUPPORT

    FwPrint( "\r\n %s %s ", Str, EisaCfgMessages[ErrorCode] );
    if ( strlen(Str) + strlen(EisaCfgMessages[ErrorCode]) + 2 < 36 )
    {
        FwMoveCursorToColumn( 37 );
    }
    FwPrint( EISA_ERROR1_MSG );
    FwStallExecution(1500000);

    return;
}







// ----------------------------------------------------------------------------
// PROCEDURE:           EisaCheckpointFirstFase:
//
// DESCRIPTION:         This function displays the specified checkpoint
//                      number on the internal LED and sends it to the
//                      parallel port.
//
// ARGUMENTS:           Chk             checkpoint number
//
// RETURN:              none
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
//
// ----------------------------------------------------------------------------
//

VOID
EisaCheckpointFirstFase
    (
    IN EISA_CHECKPOINT  Chk
    )
{
    ULONG TestFlags;

    PRINTDBG("EisaCheckpointFirstFase\n\r");    // DEBUG SUPPORT

    TestFlags = ( (ULONG)EisaCheckpointInfo[ Chk ].SubLed << 28 ) +
                ( (ULONG)EisaCheckpointInfo[ Chk ].Led    << 24 ) +
                ( (ULONG)EisaCheckpointInfo[ Chk ].SubPar << 8  ) +
                ( (ULONG)EisaCheckpointInfo[ Chk ].Par          );

// NOTE: The parallel port test flag support is not used on JAZZ.
//    DisplayOnParallelPort( TestFlags );

    return;
}








// ----------------------------------------------------------------------------
// PROCEDURE:           EisaCheckpointFinalFase:
//
// DESCRIPTION:         This function returns the value of the specified
//                      real-time clock internal address.
//
// ARGUMENTS:           Chk             checkpoint number
//                      Passed          pass or fail
//
// RETURN:              Repeat          = TRUE  repeat checkpoint
//                                      = FALSE continue
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
//
// ----------------------------------------------------------------------------
//

BOOLEAN
EisaCheckpointFinalFase
    (
    IN EISA_CHECKPOINT  Chk,
    IN BOOLEAN          Passed
    )
{
    ULONG       TestFlags;

    PRINTDBG("EisaCheckpointFinalFase\n\r");    // DEBUG SUPPORT

    if ( Passed )
    {
        EisaCheckpointInfo[ Chk ].Flags &= ~0x01;       // all fine
        EisaCheckpointInfo[ Chk ].Flags &= ~0x08;       // no message
    }
    else
    {
        EisaCheckpointInfo[ Chk ].Flags |= 0x01;        // error

        if ( EisaCheckpointInfo[ Chk ].Flags & 0x08 )   // display message
        {
            FwPrint( "%s", EisaCheckpointInfo[ Chk ].Msg );
            FwStallExecution(1500000);
        }
    }

    TestFlags = (( (ULONG)EisaCheckpointInfo[ Chk ].SubLed << 28 ) +
                 ( (ULONG)EisaCheckpointInfo[ Chk ].Led    << 24 ) +
                 ( (ULONG)EisaCheckpointInfo[ Chk ].Flags  << 16 ) +
                 ( (ULONG)EisaCheckpointInfo[ Chk ].SubPar << 8  ) +
                 ( (ULONG)EisaCheckpointInfo[ Chk ].Par          ));

// TEMPTEMP: Changed until we get the EvaluateTestResult routine from Olivetti.
//    return EvaluateTestResult( TestFlags ) == ESUCCESS ? FALSE : TRUE;

    return(FALSE);  // Never repeat.
}










// ----------------------------------------------------------------------------
// PROCEDURE:           EisaReadReadyId:
//
// DESCRIPTION:         This function reads the eisa id of the specified
//                      slot.
//
// ARGUMENTS:           EisaIoStart     Starting eisa I/O address.
//                      SlotNumber      Eisa slot number.
//                      AdapId          Eisa ID returned.
//
// RETURN:              FALSE           Time-out error
//                      TRUE            Valid adapter Id
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//

BOOLEAN
EisaReadReadyId
        (
        IN PUCHAR EisaIoStart,
        IN ULONG SlotNumber,
        OUT PULONG AdapId
        )
{
    // define local variables

    BOOLEAN Ready=TRUE;

    PRINTDBG("EisaReadReadyId\n\r");    // DEBUG SUPPORT


    //
    // read adapter id
    //

    EisaReadId(EisaIoStart, SlotNumber, AdapId);


    //
    // check if adapter id is ready
    //

    if ( *AdapId & NO_ADAP_ID )
    {
        *AdapId = NO_ADAP_ID;                   // empty slot
    }
    else if ((*AdapId & WAIT_ADAP_ID) == WAIT_ADAP_ID)
    {
        Ready = FALSE;                          // adapter not ready
    }

    return Ready;
}




// ----------------------------------------------------------------------------
// PROCEDURE:           EisaReadId:
//
// DESCRIPTION:         This function reads the eisa id of the specified
//                      slot.
//
// ARGUMENTS:           EisaIoStart     Starting eisa I/O address.
//                      SlotNumber      Eisa slot number.
//                      AdapId          Eisa ID returned.
//
// RETURN:              none
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//

VOID
EisaReadId
        (
        IN PUCHAR EisaIoStart,
        IN ULONG SlotNumber,
        OUT PULONG AdapId
        )
{
    // define local variables

    PUCHAR AdapIdPort;                  // eisa I/O ID port
    PUCHAR RefreshPort;                 // eisa refresh port
    UCHAR  RefreshStatus;               // eisa refresh status (port 61h)
    ULONG  Retry;                       // # retry

    PRINTDBG("EisaReadId\n\r");         // DEBUG SUPPORT

    // initialize variables

    AdapIdPort = EisaIoStart + SlotNumber * 0x1000 + EISA_PRODUCT_ID;
    RefreshPort = EisaIoStart + EISA_SYS_CTRL_PORTB;

    // wait for the end of a refresh cycle (bit 4 of port 61h toggles)

    for ( Retry = EISA_RFR_RETRY,
          RefreshStatus = READ_REGISTER_UCHAR(RefreshPort) & EISA_REFRESH;

          Retry &&
          RefreshStatus == (READ_REGISTER_UCHAR(RefreshPort) & EISA_REFRESH);

          Retry-- );

    // write 0xFF to the adapter ID port

    EisaOutUchar(AdapIdPort, 0xFF);

    // read adapter id

    *AdapId = EisaInUchar(AdapIdPort++);
    *AdapId = *AdapId << BITSXBYTE | EisaInUchar(AdapIdPort++);
    *AdapId = *AdapId << BITSXBYTE | EisaInUchar(AdapIdPort++);
    *AdapId = *AdapId << BITSXBYTE | EisaInUchar(AdapIdPort++);

    // all done, return.

    return;
}







// ----------------------------------------------------------------------------
// PROCEDURE:           EisaMemIni:
//
// DESCRIPTION:         This function allocates memory for the descriptor
//                      pool and computes the top address and the length
//                      of a physical contiguous memory block to be used as
//                      OMF device drivers and dynamic memory pool.
//                      Note that only the memory really used will be
//                      allocated.
//
// ARGUMENTS:           none
//
// RETURN:              TRUE            all done
//                      FALSE           memory initialization error
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:             pFwMdPool               // descriptor pool
//                      MemorySize              // memory size in Mbytes
//                      EisaPoolSize            // # bytes really used
//                      EisaFreeTop             // top of free mem
//                      EisaDynMemSize          // dynamic memory size (bytes)
//                      EisaFreeBytes           // free bytes left
//
// NOTES:
// ----------------------------------------------------------------------------
//

// NOTE: Not used for JAZZ.
#if 0

BOOLEAN
EisaMemIni
    (
    VOID
    )
{
    FW_MD BuffFwMd;
    PVOID Dummy;

    PRINTDBG("EisaMemIni\n\r");                 // DEBUG SUPPORT

    //
    // allocate descriptor pool
    //

    if ( (pFwMdPool = (PFW_MD)FwAllocatePool( sizeof(FW_MD)*FW_MD_POOL ))
                    == NULL )
    {
        return FALSE;
    }

    //
    // set all the necessary TLB entries to map the whole system memory
    //

    RtlZeroMemory( &BuffFwMd, sizeof(FW_MD));
    BuffFwMd.Size       = 256 << 20;
    BuffFwMd.PagNumb    = 256 << (20 - PAGE_SHIFT);
    BuffFwMd.Cache      = TRUE;

    if ( AllocateMemoryResources( &BuffFwMd ) != ESUCCESS )
    {
        return FALSE;
    }

    //
    // compute OMF device drivers and dynamic memory pool area
    //

    EisaPoolSize = EisaDynMemSize = EISA_DYN_MEM_SIZE;

    if ( MemorySize >= 16 )
    {
        //
        // we don't use the memory above 16Mbytes because in this way we
        // can use this logic in a machine without translation registers
        // (logical I/O to physical) for the ISA boards which have a
        // transfer range of 24 bits (16Mbytes).
        //

        EisaFreeTop      = EISA_FREE_TOP_16;
        EisaFreeBytes    = EISA_FREE_BYTES_16;
    }
    else if ( MemorySize >= 12 )
    {
        EisaFreeTop      = EISA_FREE_TOP_12;
        EisaFreeBytes    = EISA_FREE_BYTES_12;
    }
    else if ( MemorySize >= 8 )
    {
        EisaFreeTop     = EISA_FREE_TOP_8;
        EisaFreeBytes   = EISA_FREE_BYTES_8;
    }
    else
    {
        return FALSE;
    }

    EisaFreeBytes   -= EisaDynMemSize;

    return TRUE;
}

#endif // 0






// ----------------------------------------------------------------------------
// PROCEDURE:           EisaDynMemIni:
//
// DESCRIPTION:         This function allocates the requested space for the
//                      the dynamic memory allocation.
//
// ARGUMENTS:           none
//
// RETURN:              none
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:             EisaFreeTop             top of free mem
//                      EisaDynMemSize          dynamic memory size (bytes)
//                      EisaPoolSize            EISA pool size (bytes)
//
// NOTES:
// ----------------------------------------------------------------------------
//

// NOTE: Not used for JAZZ.
#if 0

VOID
EisaDynMemIni
    (
    VOID
    )
{
    //
    // define local variables
    //

    ULONG       BytesToPage;                    // bytes left to make a page
    PHEADER     pHdr;                           // memory descriptor header ptr
    PVOID       Buffer;                         // data area

    PRINTDBG("EisaDynMemIni\n\r");              // DEBUG SUPPORT

    //
    // align the dynamic memory buffer on a page boundary
    //

    BytesToPage      = PAGE_SIZE - (EisaDynMemSize & ((1 << PAGE_SHIFT) - 1));
    EisaDynMemSize  += BytesToPage;
    EisaPoolSize    += BytesToPage;
    EisaFreeTop     -= EisaDynMemSize;

    //
    // initialize first memory descriptor
    //

    pHdr         = (PHEADER)EisaFreeTop;
    Buffer       = (PVOID)(pHdr + 1);
    pHdr->m.id   = Buffer;
    pHdr->m.size = EisaDynMemSize/sizeof(HEADER);
    EisaFreeMemory( Buffer );

    return;
}

#endif // 0


// ----------------------------------------------------------------------------
// PROCEDURE:           FwGetPath:
//
// DESCRIPTION:         This function builds the path name for the specified
//                      component.
//
// ARGUMENTS:           Component       Component pointer.
//                      Str             Path name pointer.
//
// RETURN:              Str             Path name pointer.
//
// ASSUMPTIONS:         The string must be large enoungh to hold the
//                      requested path name.
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//

PCHAR
FwGetPath
        (
        IN PCONFIGURATION_COMPONENT Component,
        OUT PCHAR Str
        )
{
    PCONFIGURATION_COMPONENT    pComp;

    PRINTDBG("FwGetPath\n\r");  // DEBUG SUPPORT

    if ( (pComp = FwGetParent( Component )) != NULL )
    {
        FwGetPath( pComp, Str);
        strcat( Str, FwGetMnemonic( Component ) );
        sprintf( Str + strlen( Str ), "(%lu)", Component->Key);
    }
    else
    {
        *Str = '\0';
    }
    return Str;
}








// ----------------------------------------------------------------------------
// PROCEDURE:           FwDelCfgTreeNode:
//
// DESCRIPTION:         This function removes from the configuration tree
//                      the specified component and all its children.
//
// ARGUMENTS:           pComp           component pointer.
//                      Peer            = TRUE  delete all its peers.
//                                      = FALSE delete just this branch.
//
// RETURN:              none
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//

VOID
FwDelCfgTreeNode
    (
    IN PCONFIGURATION_COMPONENT pComp,
    IN BOOLEAN                  Peer
    )
{
    //
    // define local variables
    //

    PCONFIGURATION_COMPONENT NextComp;

    PRINTDBG("FwDelCfgTreeNode\n\r");           // DEBUG SUPPORT

    //
    // check for a child
    //

    if ( (NextComp = FwGetChild( pComp )) != NULL )
    {
        FwDelCfgTreeNode( NextComp, TRUE );
    }

    //
    // check for a peer.
    //

    if ( Peer  &&  (NextComp = FwGetPeer( pComp )) != NULL )
    {
        FwDelCfgTreeNode( NextComp, TRUE );
    }

    //
    // this is a leaf, delete it
    //

    FwDeleteComponent( pComp );

    //
    // all done
    //

    return;
}








// ----------------------------------------------------------------------------
// PROCEDURE:           FwGetMnemonic:
//
// DESCRIPTION:         This function stores the mnemonic name for the
//                      requested component type.
//
// ARGUMENTS:           Component       Component pointer.
//
// RETURN:              Str             Mnemonic pointer
//
// ASSUMPTIONS:         none
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//

PCHAR
FwGetMnemonic
        (
        IN PCONFIGURATION_COMPONENT Component
        )
{
    PRINTDBG("FwGetMnemonic\n\r");      // DEBUG SUPPORT

    return MnemonicTable[Component->Type];
}






// ----------------------------------------------------------------------------
// PROCEDURE:           FwValidMnem:
//
// DESCRIPTION:         This function validates the specified mnemonic.
//                      If the mnemonic is valid, a TURE value is returned,
//                      otherwise a FALSE is returned.
//
// ARGUMENTS:           Str             Mnemonic pointer
//
// RETURN:              FALSE           Mnemonic incorrect
//                      TRUE            Mnemonic correct
//
// ASSUMPTIONS:         none
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//

BOOLEAN
FwValidMnem
        (
        IN PCHAR Str
        )
{
    // define local variables

    CONFIGURATION_TYPE CfgType;

    PRINTDBG("FwValidMnem\n\r");        // DEBUG SUPPORT

    // check the mnemonic table

    for ( CfgType = ArcSystem;
          CfgType < MaximumType  &&  strcmp( MnemonicTable[ CfgType ], Str );
          CfgType++ );

    return CfgType < MaximumType ? TRUE : FALSE;
}



// ----------------------------------------------------------------------------
// GLOBAL:      I/O functions variables
// ----------------------------------------------------------------------------

PCHAR   AsciiBlock;                     // pointer the ASCII block
ULONG   AsciiBlockLength = 0;           // length of the ASCII block




// ----------------------------------------------------------------------------
// PROCEDURE:           FwStoreStr:
//
// DESCRIPTION:         This function stores the specified string within
//                      the ASCII block.  The NULL pointer is returned if
//                      there isn't space available for the string.
//
// ARGUMENTS:           Str             String pointer
//
// RETURN:              Str             String pointer
//
// ASSUMPTIONS:
//
// CALLS:
//
// GLOBALS:
//
// NOTES:
// ----------------------------------------------------------------------------
//

PCHAR
FwStoreStr
    (
    IN PCHAR Str
    )
{

    PRINTDBG("FwStoreStr\n\r");         // DEBUG SUPPORT

    // if not enough space, allocate new ASCII block

    if ( AsciiBlockLength < strlen( Str ) + 1 )
    {
        if((AsciiBlock = (PUCHAR)FwAllocatePool(ASCII_BLOCK_SIZE)) == NULL)
        {
            return NULL;
        }
    }

    // store the string and update the pointers.

    Str = strcpy( AsciiBlock, Str );
    AsciiBlock       += strlen( Str ) + 1;
    AsciiBlockLength  = ASCII_BLOCK_SIZE - (strlen( Str ) + 1);

    // all done, return the new string pointer

    return Str;
}
