|
|
// ----------------------------------------------------------------------------
// 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
//
(PEISA_PROCESS_EOI_RTN)SYSTEM_BLOCK->Adapter0Vector [ProcessEOIRoutine] = EisaProcessEndOfInterrupt; // [ProcessEOIRoutine] = FwpReservedRoutine;
(PEISA_TEST_INT_RTN)SYSTEM_BLOCK->Adapter0Vector [TestIntRoutine] = EisaTestEisaInterrupt; // [TestIntRoutine] = FwpReservedRoutine;
(PEISA_REQ_DMA_XFER_RTN)SYSTEM_BLOCK->Adapter0Vector // [RequestDMARoutine] = EisaRequestEisaDmaTransfer;
[RequestDMARoutine] = FwpReservedRoutine;
(PEISA_ABORT_DMA_RTN)SYSTEM_BLOCK->Adapter0Vector // [AbortDMARoutine] = EisaAbortEisaDmaTransfer;
[AbortDMARoutine] = FwpReservedRoutine;
(PEISA_DMA_XFER_STATUS_RTN)SYSTEM_BLOCK->Adapter0Vector // [GetDMAStatusRoutine] = EisaGetEisaDmaTransferStatus;
[GetDMAStatusRoutine] = FwpReservedRoutine;
(PEISA_LOCK_RTN)SYSTEM_BLOCK->Adapter0Vector // [DoLockRoutine] = EisaDoLockedOperation;
[DoLockRoutine] = FwpReservedRoutine;
(PEISA_REQUEST_BUS_MASTER_RTN)SYSTEM_BLOCK->Adapter0Vector // [RequestBusMasterRoutine] = EisaRequestEisaBusMasterTransfer;
[RequestBusMasterRoutine] = FwpReservedRoutine;
(PEISA_RELEASE_BUS_MASTER_RTN)SYSTEM_BLOCK->Adapter0Vector // [ReleaseBusMasterRoutine] = EisaReleaseEisaBusMasterTransfer;
[ReleaseBusMasterRoutine] = FwpReservedRoutine;
(PEISA_REQUEST_CPU_TO_BUS_ACCESS_RTN)SYSTEM_BLOCK->Adapter0Vector // [RequestCpuAccessToBusRoutine] = EisaRequestCpuAccessToEisaBus;
[RequestCpuAccessToBusRoutine] = FwpReservedRoutine;
(PEISA_RELEASE_CPU_TO_BUS_ACCESS_RTN)SYSTEM_BLOCK->Adapter0Vector // [ReleaseCpuAccessToBusRoutine] = EisaReleaseCpuAccessToEisaBus;
[ReleaseCpuAccessToBusRoutine] = FwpReservedRoutine;
(PEISA_FLUSH_CACHE_RTN)SYSTEM_BLOCK->Adapter0Vector // [FlushCacheRoutine] = EisaFlushCache;
[FlushCacheRoutine] = FwpReservedRoutine;
(PEISA_INVALIDATE_CACHE_RTN)SYSTEM_BLOCK->Adapter0Vector // [InvalidateCacheRoutine] = EisaInvalidateCache;
[InvalidateCacheRoutine] = FwpReservedRoutine;
(PEISA_BEGIN_CRITICAL_SECTION_RTN)SYSTEM_BLOCK->Adapter0Vector [BeginCriticalSectionRoutine] = EisaBeginCriticalSection; // [BeginCriticalSectionRoutine] = FwpReservedRoutine;
(PEISA_RESERVED_RTN)SYSTEM_BLOCK->Adapter0Vector [ReservedRoutine] = NULL;
(PEISA_END_CRITICAL_SECTION_RTN)SYSTEM_BLOCK->Adapter0Vector [EndCriticalSectionRoutine] = EisaEndCriticalSection; // [EndCriticalSectionRoutine] = FwpReservedRoutine;
(PEISA_GENERATE_TONE_RTN)SYSTEM_BLOCK->Adapter0Vector [GenerateToneRoutine] = EisaGenerateTone;
(PEISA_FLUSH_WRITE_BUFFER_RTN)SYSTEM_BLOCK->Adapter0Vector // [FlushWriteBuffersRoutine] = EisaFlushWriteBuffers;
[FlushWriteBuffersRoutine] = FwpReservedRoutine;
(PEISA_YIELD_RTN)SYSTEM_BLOCK->Adapter0Vector // [YieldRoutine] = EisaYield;
[YieldRoutine] = FwpReservedRoutine;
(PEISA_STALL_PROCESSOR_RTN)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;
((PFW_MD)pInfo)++;
//
// 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
((PFW_MD)pInfo)++;
//
// slot info initialization
//
pBusInfo->SlotsInfo = pSlotsInfo = (PEISA_SLOTS_INFO)pInfo; pSlotsInfo->PhysSlots = PHYS_0_SLOTS; pSlotsInfo->VirSlots = VIR_0_SLOTS; ((PEISA_SLOTS_INFO)pInfo)++;
//
// DMA info initialization
//
pBusInfo->DmaInfo = pDmaInfo = (PEISA_DMA_INFO)pInfo; pDmaInfo->Flags.IniDone = 0; ((PEISA_DMA_INFO)pInfo)++;
//
// PIC info initialization
//
pBusInfo->IntInfo = pIntInfo = (PEISA_INT_INFO)pInfo; pIntInfo->Flags.IniDone = 0; ((PEISA_INT_INFO)pInfo)++;
//
// 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; }
|