summaryrefslogtreecommitdiffstats
path: root/private/ntos/fw/alpha
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/fw/alpha
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ntos/fw/alpha')
-rw-r--r--private/ntos/fw/alpha/arceisa.h547
-rw-r--r--private/ntos/fw/alpha/ati.h389
-rw-r--r--private/ntos/fw/alpha/atidisk/68800.h362
-rw-r--r--private/ntos/fw/alpha/atidisk/sample.txt131
-rw-r--r--private/ntos/fw/alpha/bldrstub.c287
-rw-r--r--private/ntos/fw/alpha/conftest.c1065
-rw-r--r--private/ntos/fw/alpha/conftest.rsp11
-rw-r--r--private/ntos/fw/alpha/debug.h7
-rw-r--r--private/ntos/fw/alpha/eisafunc.c693
-rw-r--r--private/ntos/fw/alpha/eisaini.c3420
-rw-r--r--private/ntos/fw/alpha/eisamisc.c213
-rw-r--r--private/ntos/fw/alpha/eisapod.c3694
-rw-r--r--private/ntos/fw/alpha/eisastr.h39
-rw-r--r--private/ntos/fw/alpha/eisausa.c102
-rw-r--r--private/ntos/fw/alpha/fakebldr.c165
-rw-r--r--private/ntos/fw/alpha/fakebldr.rsp10
-rw-r--r--private/ntos/fw/alpha/fwcallbk.h279
-rw-r--r--private/ntos/fw/alpha/fwchkstk.s136
-rw-r--r--private/ntos/fw/alpha/fwhalt.c441
-rw-r--r--private/ntos/fw/alpha/fwio.c1628
-rw-r--r--private/ntos/fw/alpha/fwkd.c699
-rw-r--r--private/ntos/fw/alpha/fwload.c1035
-rw-r--r--private/ntos/fw/alpha/fwmemdef.h101
-rw-r--r--private/ntos/fw/alpha/fwp.h720
-rw-r--r--private/ntos/fw/alpha/fwpexcpt.h148
-rw-r--r--private/ntos/fw/alpha/fwprint.c138
-rw-r--r--private/ntos/fw/alpha/fwrstb.c172
-rw-r--r--private/ntos/fw/alpha/fwsignal.c381
-rw-r--r--private/ntos/fw/alpha/fwstring.h301
-rw-r--r--private/ntos/fw/alpha/fwtime.c171
-rw-r--r--private/ntos/fw/alpha/fwupusa.c168
-rw-r--r--private/ntos/fw/alpha/fwusa.c470
-rw-r--r--private/ntos/fw/alpha/inc.h908
-rw-r--r--private/ntos/fw/alpha/iodevice.h258
-rw-r--r--private/ntos/fw/alpha/jenassem.s579
-rw-r--r--private/ntos/fw/alpha/jenfonts.c961
-rw-r--r--private/ntos/fw/alpha/jensen/alpha/aha174x.c2035
-rw-r--r--private/ntos/fw/alpha/jensen/alpha/chkstall.c142
-rw-r--r--private/ntos/fw/alpha/jensen/alpha/jenstubs.c46
-rw-r--r--private/ntos/fw/alpha/jensen/alpha/jnfs.c413
-rw-r--r--private/ntos/fw/alpha/jensen/alpha/jnsetcfg.c1073
-rw-r--r--private/ntos/fw/alpha/jensen/alpha/jxmemory.c817
-rw-r--r--private/ntos/fw/alpha/jensen/alpha/led.h36
-rw-r--r--private/ntos/fw/alpha/jensen/alpha/machdef.h83
-rw-r--r--private/ntos/fw/alpha/jensen/alpha/selftest.c599
-rw-r--r--private/ntos/fw/alpha/jensen/alpha/tbaqva.c413
-rw-r--r--private/ntos/fw/alpha/jensen/alpha/version.c34
-rw-r--r--private/ntos/fw/alpha/jensen/alpha/xxstring.c91
-rw-r--r--private/ntos/fw/alpha/jensen/be_firm.cmd107
-rw-r--r--private/ntos/fw/alpha/jensen/clean.cmd11
-rw-r--r--private/ntos/fw/alpha/jensen/conftest.rsp10
-rw-r--r--private/ntos/fw/alpha/jensen/fakebldr.rsp10
-rw-r--r--private/ntos/fw/alpha/jensen/linkfsb.rsp48
-rw-r--r--private/ntos/fw/alpha/jensen/linkjens.rsp67
-rw-r--r--private/ntos/fw/alpha/jensen/linkupd.rsp21
-rw-r--r--private/ntos/fw/alpha/jensen/makefile6
-rw-r--r--private/ntos/fw/alpha/jensen/makefile.inc423
-rw-r--r--private/ntos/fw/alpha/jensen/readmekd.txt68
-rw-r--r--private/ntos/fw/alpha/jensen/sources220
-rw-r--r--private/ntos/fw/alpha/jnfs.h84
-rw-r--r--private/ntos/fw/alpha/jnfsfsb.h1
-rw-r--r--private/ntos/fw/alpha/jnfsinit.c294
-rw-r--r--private/ntos/fw/alpha/jnfsstb.c335
-rw-r--r--private/ntos/fw/alpha/jnfsstub.s353
-rw-r--r--private/ntos/fw/alpha/jnsetcom.c862
-rw-r--r--private/ntos/fw/alpha/jnsetenv.c408
-rw-r--r--private/ntos/fw/alpha/jnsetmak.c2442
-rw-r--r--private/ntos/fw/alpha/jnsetset.c1007
-rw-r--r--private/ntos/fw/alpha/jnsettim.c421
-rw-r--r--private/ntos/fw/alpha/jnsnprom.h222
-rw-r--r--private/ntos/fw/alpha/jnsnvdeo.h206
-rw-r--r--private/ntos/fw/alpha/jnupass.s181
-rw-r--r--private/ntos/fw/alpha/jnupdate.c1450
-rw-r--r--private/ntos/fw/alpha/jnupdate.h1
-rw-r--r--private/ntos/fw/alpha/jnupstub.c61
-rw-r--r--private/ntos/fw/alpha/jnvendor.h57
-rw-r--r--private/ntos/fw/alpha/jxboot.c2251
-rw-r--r--private/ntos/fw/alpha/jxconfig.c1955
-rw-r--r--private/ntos/fw/alpha/jxdisp.c3460
-rw-r--r--private/ntos/fw/alpha/jxenvir.c1020
-rw-r--r--private/ntos/fw/alpha/jxfboot.c2273
-rw-r--r--private/ntos/fw/alpha/jxfwhal.h109
-rw-r--r--private/ntos/fw/alpha/jxhwsup.c1936
-rw-r--r--private/ntos/fw/alpha/jxkbd.c581
-rw-r--r--private/ntos/fw/alpha/jxreboot.c157
-rw-r--r--private/ntos/fw/alpha/jxserial.c590
-rw-r--r--private/ntos/fw/alpha/jxsysid.c168
-rw-r--r--private/ntos/fw/alpha/jxvendor.c750
-rw-r--r--private/ntos/fw/alpha/kbdmouse.h164
-rw-r--r--private/ntos/fw/alpha/kbdtest.c414
-rw-r--r--private/ntos/fw/alpha/kdstubs.c201
-rw-r--r--private/ntos/fw/alpha/monitor.c1785
-rw-r--r--private/ntos/fw/alpha/monitor.h214
-rw-r--r--private/ntos/fw/alpha/oli2msft.h39
-rw-r--r--private/ntos/fw/alpha/omf.c3794
-rw-r--r--private/ntos/fw/alpha/pal/checked/a221064.palbin0 -> 35328 bytes
-rw-r--r--private/ntos/fw/alpha/pal/checked/a221066.palbin0 -> 27136 bytes
-rw-r--r--private/ntos/fw/alpha/pal/checked/a221164.palbin0 -> 33280 bytes
-rw-r--r--private/ntos/fw/alpha/pal/checked/a321064.palbin0 -> 27648 bytes
-rw-r--r--private/ntos/fw/alpha/pal/free/a221064.palbin0 -> 32768 bytes
-rw-r--r--private/ntos/fw/alpha/pal/free/a221066.palbin0 -> 25088 bytes
-rw-r--r--private/ntos/fw/alpha/pal/free/a221164.palbin0 -> 31744 bytes
-rw-r--r--private/ntos/fw/alpha/pal/free/a321064.palbin0 -> 25600 bytes
-rw-r--r--private/ntos/fw/alpha/readme.txt11
-rw-r--r--private/ntos/fw/alpha/rom.c1079
-rw-r--r--private/ntos/fw/alpha/rom.h182
-rw-r--r--private/ntos/fw/alpha/selfmap.h439
-rw-r--r--private/ntos/fw/alpha/selftest.h119
-rw-r--r--private/ntos/fw/alpha/stubs.c376
-rw-r--r--private/ntos/fw/alpha/tools/fwimagen/fwimagen.c135
-rw-r--r--private/ntos/fw/alpha/tools/fwpack/fsbpack.c351
-rw-r--r--private/ntos/fw/alpha/tools/fwpack/fwpack.c351
-rw-r--r--private/ntos/fw/alpha/xxstring.h53
113 files changed, 60944 insertions, 0 deletions
diff --git a/private/ntos/fw/alpha/arceisa.h b/private/ntos/fw/alpha/arceisa.h
new file mode 100644
index 000000000..df162ec7a
--- /dev/null
+++ b/private/ntos/fw/alpha/arceisa.h
@@ -0,0 +1,547 @@
+// -----------------------------------------------------------------------------
+//
+// Copyright (c) 1992 Olivetti
+//
+// File: arceisa.h
+//
+// Description: ARC-EISA Addendum Structures and Defines.
+//
+// -----------------------------------------------------------------------------
+
+
+//
+// Define the EISA firmware entry points
+//
+
+typedef enum _EISA_FIRMWARE_ENTRY
+ {
+ ProcessEOIRoutine,
+ TestIntRoutine,
+ RequestDMARoutine,
+ AbortDMARoutine,
+ GetDMAStatusRoutine,
+ DoLockRoutine,
+ RequestBusMasterRoutine,
+ ReleaseBusMasterRoutine,
+ RequestCpuAccessToBusRoutine,
+ ReleaseCpuAccessToBusRoutine,
+ FlushCacheRoutine,
+ InvalidateCacheRoutine,
+ ReservedRoutine,
+ BeginCriticalSectionRoutine,
+ EndCriticalSectionRoutine,
+ GenerateToneRoutine,
+ FlushWriteBuffersRoutine,
+ YieldRoutine,
+ StallProcessorRoutine,
+ MaximumEisaRoutine
+ } EISA_FIRMWARE_ENTRY;
+
+
+//
+// Define EISA interrupt functions
+//
+
+typedef
+ARC_STATUS
+(*PEISA_PROCESS_EOI_RTN)
+ (
+ IN ULONG BusNumber,
+ IN USHORT IRQ
+ );
+
+typedef
+BOOLEAN_ULONG
+(*PEISA_TEST_INT_RTN)
+ (
+ IN ULONG BusNumber,
+ IN USHORT IRQ
+ );
+
+//
+// Define EISA DMA functions
+//
+
+typedef enum _DMA_TRANSFER_TYPE
+ {
+ DmaVerify,
+ DmaWrite,
+ DmaRead,
+ DmaMaxType
+ } DMA_TRANSFER_TYPE, *PDMA_TRANSFER_TYPE;
+
+typedef enum _DMA_TRANSFER_MODE
+ {
+ DmaDemand,
+ DmaSingle,
+ DmaBlock,
+ DmaCascade,
+ DmaMaxMode
+ } DMA_TRANSFER_MODE, *PDMA_TRANSFER_MODE;
+
+typedef enum _DMA_TIMING_MODE
+ {
+ DmaIsaCompatible,
+ DmaTypeA,
+ DmaTypeB,
+ DmaBurst,
+ DmaMaxTiming
+ } DMA_TIMING_MODE, *PDMA_TIMING_MODE;
+
+typedef enum _DMA_ADDRESSING_MODE
+ {
+ Dma8Bit,
+ Dma16sBit,
+ Dma32Bit,
+ Dma16Bit,
+ DmaMaxAddressing
+ } DMA_ADDRESSING_MODE, *PDMA_ADDRESSING_MODE;
+
+typedef struct _DMA_TRANSFER
+ {
+ DMA_TRANSFER_MODE TransferMode;
+ ULONG ChannelNumber;
+ DMA_TRANSFER_TYPE TransferType;
+ ULONG Size;
+ PVOID Buffer;
+ } DMA_TRANSFER, *PDMA_TRANSFER;
+
+typedef struct _DMA_STATUS
+ {
+ BOOLEAN_ULONG CompleteTransfer;
+ ULONG ByteTransferred;
+ } DMA_STATUS, *PDMA_STATUS;
+
+typedef
+ARC_STATUS
+(*PEISA_REQ_DMA_XFER_RTN)
+ (
+ IN ULONG BusNumber,
+ IN PDMA_TRANSFER pDmaTransfer
+ );
+
+typedef
+ARC_STATUS
+(*PEISA_ABORT_DMA_RTN)
+ (
+ IN ULONG BusNumber,
+ IN PDMA_TRANSFER pDmaTransfer
+ );
+
+typedef
+ARC_STATUS
+(*PEISA_DMA_XFER_STATUS_RTN)
+ (
+ IN ULONG BusNumber,
+ IN PDMA_TRANSFER pDmaTransfer,
+ OUT PDMA_STATUS pDmaStatus
+ );
+
+//
+// Define EISA lock function
+//
+
+typedef enum _EISA_LOCK_OPERATION
+ {
+ Exchange,
+ LockMaxOperation
+ } EISA_LOCK_OPERATION;
+
+
+typedef enum _SEMAPHORE_SIZE
+ {
+ ByteSemaphore,
+ HalfWordSemaphore,
+ WordSemaphore,
+ MaxSemaphore
+ } SEMAPHORE_SIZE;
+
+typedef
+ARC_STATUS
+(*PEISA_LOCK_RTN)
+ (
+ IN ULONG BusNumber,
+ IN EISA_LOCK_OPERATION Operation,
+ IN PVOID Semaphore,
+ IN SEMAPHORE_SIZE SemaphoreSize,
+ IN PVOID OperationArgument,
+ OUT PVOID OperationResult
+ );
+
+//
+// Define EISA bus master functions.
+//
+
+typedef enum _BUS_MASTER_TRANSFER_TYPE
+ {
+ BusMasterWrite,
+ BusMasterRead,
+ BusMasterMaxType
+ } BUS_MASTER_TRANSFER_TYPE, *PBUS_MASTER_TRANSFER_TYPE;
+
+typedef enum _ADDRESS_RESTRICTION
+ {
+ LimitNone,
+ Limit16Mb,
+ Limit4Gb,
+ LimitMax
+ } ADDRESS_RESTRICTION, *PADDRESS_RESTRICTION;
+
+typedef struct _BUS_MASTER_TRANSFER
+ {
+ ADDRESS_RESTRICTION Limit;
+ ULONG SlotNumber;
+ BUS_MASTER_TRANSFER_TYPE TransferType;
+ ULONG Size;
+ PVOID Buffer;
+ } BUS_MASTER_TRANSFER, *PBUS_MASTER_TRANSFER;
+
+typedef
+ARC_STATUS
+(*PEISA_REQUEST_BUS_MASTER_RTN)
+ (
+ IN ULONG BusNumber,
+ IN PBUS_MASTER_TRANSFER pBusMasterTransfer,
+ OUT ULONG *TranslateBufferAddress
+ );
+
+typedef
+ARC_STATUS
+(*PEISA_RELEASE_BUS_MASTER_RTN)
+ (
+ IN ULONG BusNumber,
+ IN PBUS_MASTER_TRANSFER pBusMasterTransfer,
+ IN ULONG TranslateBufferAddress
+ );
+
+//
+// Define EISA slave functions
+//
+
+typedef struct _SLAVE_TRANSFER
+ {
+ ULONG SlotNumber;
+ ULONG Size;
+ ULONG Buffer;
+ } SLAVE_TRANSFER, *PSLAVE_TRANSFER;
+
+typedef
+ARC_STATUS
+(*PEISA_REQUEST_CPU_TO_BUS_ACCESS_RTN)
+ (
+ IN ULONG BusNumber,
+ IN PSLAVE_TRANSFER pSlaveTransfer,
+ OUT PVOID *TranslatedBufferAddress
+ );
+
+typedef
+ARC_STATUS
+(*PEISA_RELEASE_CPU_TO_BUS_ACCESS_RTN)
+ (
+ IN ULONG BusNumber,
+ IN PSLAVE_TRANSFER pSlaveTransfer,
+ IN PVOID TranslateBufferAddress
+ );
+
+typedef
+VOID
+(*PEISA_FLUSH_CACHE_RTN)
+ (
+ IN PVOID Address,
+ IN ULONG Length
+ );
+
+typedef
+VOID
+(*PEISA_INVALIDATE_CACHE_RTN)
+ (
+ IN PVOID Address,
+ IN ULONG Length
+ );
+
+typedef
+VOID
+(*PEISA_RESERVED_RTN)
+ (
+ VOID
+ );
+
+typedef
+VOID
+(*PEISA_BEGIN_CRITICAL_SECTION_RTN)
+ (
+ VOID
+ );
+
+typedef
+VOID
+(*PEISA_END_CRITICAL_SECTION_RTN)
+ (
+ VOID
+ );
+
+typedef
+ARC_STATUS
+(*PEISA_GENERATE_TONE_RTN)
+ (
+ IN ULONG Frequency,
+ IN ULONG Duration
+ );
+
+typedef
+VOID
+(*PEISA_FLUSH_WRITE_BUFFER_RTN)
+ (
+ VOID
+ );
+
+typedef
+BOOLEAN_ULONG
+(*PEISA_YIELD_RTN)
+ (
+ VOID
+ );
+
+typedef
+VOID
+(*PEISA_STALL_PROCESSOR_RTN)
+ (
+ IN ULONG Duration
+ );
+
+
+//
+// Define EISA callback vectors prototypes.
+//
+
+ARC_STATUS
+EisaProcessEndOfInterrupt
+ (
+ IN ULONG BusNumber,
+ IN USHORT Irq
+ );
+
+BOOLEAN_ULONG
+EisaTestEisaInterrupt
+ (
+ IN ULONG BusNumber,
+ IN USHORT Irq
+ );
+
+ARC_STATUS
+EisaRequestEisaDmaTransfer
+ (
+ IN ULONG BusNumber,
+ IN PDMA_TRANSFER pDmaTransfer
+ );
+
+ARC_STATUS
+EisaAbortEisaDmaTransfer
+ (
+ IN ULONG BusNumber,
+ IN PDMA_TRANSFER pDmaTransfer
+ );
+
+ARC_STATUS
+EisaGetEisaDmaTransferStatus
+ (
+ IN ULONG BusNumber,
+ IN PDMA_TRANSFER pDmaTransfer,
+ OUT PDMA_STATUS pDmaStatus
+ );
+
+ARC_STATUS
+EisaDoLockedOperation
+ (
+ IN ULONG BusNumber,
+ IN EISA_LOCK_OPERATION Operation,
+ IN PVOID Semaphore,
+ IN SEMAPHORE_SIZE SemaphoreSize,
+ IN PVOID OperationArgument,
+ OUT PVOID OperationResult
+ );
+
+ARC_STATUS
+EisaRequestEisaBusMasterTransfer
+ (
+ IN ULONG BusNumber,
+ IN PBUS_MASTER_TRANSFER pBusMasterTransfer,
+ OUT ULONG *TranslatedBufferAddress
+ );
+
+ARC_STATUS
+EisaReleaseEisaBusMasterTransfer
+ (
+ IN ULONG BusNumber,
+ IN PBUS_MASTER_TRANSFER pBusMasterTransfer,
+ IN ULONG TranslatedBufferAddress
+ );
+
+ARC_STATUS
+EisaRequestCpuAccessToEisaBus
+ (
+ IN ULONG BusNumber,
+ IN PSLAVE_TRANSFER pSlaveTransfer,
+ OUT PVOID *TranslatedAddress
+ );
+
+ARC_STATUS
+EisaReleaseCpuAccessToEisaBus
+ (
+ IN ULONG BusNumber,
+ IN PSLAVE_TRANSFER pSlaveTransfer,
+ IN PVOID TranslatedAddress
+ );
+
+VOID
+EisaFlushCache
+ (
+ IN PVOID Address,
+ IN ULONG Length
+ );
+
+VOID
+EisaInvalidateCache
+ (
+ IN PVOID Address,
+ IN ULONG Length
+ );
+
+VOID
+EisaBeginCriticalSection
+ (
+ IN VOID
+ );
+
+VOID
+EisaEndCriticalSection
+ (
+ IN VOID
+ );
+
+VOID
+EisaFlushWriteBuffers
+ (
+ VOID
+ );
+
+ARC_STATUS
+EisaGenerateTone
+ (
+ IN ULONG Frequency,
+ IN ULONG Duration
+ );
+
+BOOLEAN_ULONG
+EisaYield
+ (
+ VOID
+ );
+
+VOID
+EisaStallProcessor
+ (
+ IN ULONG Duration
+ );
+
+
+//
+// Define macros that call the EISA firmware routines indirectly through the
+// EISA firmware vector and provide type checking of argument values.
+//
+
+#define ArcEisaProcessEndOfInterrupt(BusNumber, IRQ) \
+ ((PEISA_PROCESS_EOI_RTN)(SYSTEM_BLOCK->Adapter0Vector[ProcessEOIRoutine])) \
+ ((BusNumber), (IRQ))
+
+#define ArcEisaTestEisaInterupt(BusNumber, IRQ) \
+ ((PEISA_TEST_INT_RTN)(SYSTEM_BLOCK->Adapter0Vector[TestIntRoutine])) \
+ ((BusNumber), (IRQ))
+
+#define ArcEisaRequestEisaDmaTransfer(BusNumber, pDmaTransfer) \
+ ((PEISA_REQ_DMA_XFER_RTN)(SYSTEM_BLOCK->Adapter0Vector[RequestDMARoutine])) \
+ ((BusNumber), (pDmaTransfer))
+
+#define ArcEisaAbortEisaDmaTransfer(BusNumber, pDmaTransfer) \
+ ((PEISA_ABORT_DMA_RTN)(SYSTEM_BLOCK->Adapter0Vector[AbortDMARoutine])) \
+ ((BusNumber), (pDmaTransfer))
+
+#define ArcEisaGetEisaDmaTransferStatus(BusNumber, pDmaTransfer, pDmaStatus) \
+ ((PEISA_DMA_XFER_STATUS_RTN)(SYSTEM_BLOCK->Adapter0Vector[GetDMAStatusRoutine])) \
+ ((BusNumber), (pDmaTransfer), (pDmaStatus))
+
+#define ArcEisaDoLockedOperation(BusNumber, Operation, Semaphore, SemaphoreSize, OperationArgument, OperationResult) \
+ ((PEISA_LOCK_RTN)(SYSTEM_BLOCK->Adapter0Vector[DoLockRoutine])) \
+ ((BusNumber), (Operation), (Semaphore), (SemaphoreSize), (OperationArgument), (OperationResult))
+
+#define ArcEisaRequestEisaBusMasterTransferCPUAddressToBusAddress(BusNumber, pBusMasterTransfer, TranslateBufferAddress) \
+ ((PEISA_REQUEST_BUS_MASTER_RTN)(SYSTEM_BLOCK->Adapter0Vector[RequestBusMasterRoutine])) \
+ ((BusNumber), (pBusMasterTransfer), (TranslateBufferAddress))
+
+#define ArcEisaReleaseEisaBusMasterTransfer(BusNumber, pBusMasterTransfer, TranslateBufferAddress) \
+ ((PEISA_RELEASE_BUS_MASTER_RTN)(SYSTEM_BLOCK->Adapter0Vector[ReleaseBusMasterRoutine])) \
+ ((BusNumber), (pBusMasterTransfer), (TranslateBufferAddress))
+
+#define ArcEisaRequestCpuAccessToEisaBus(BusNumber, pSlaveTransfer, TranslatedBufferAddress) \
+ ((PEISA_REQUEST_CPU_TO_BUS_ACCESS_RTN)(SYSTEM_BLOCK->Adapter0Vector[RequestCpuAccessToBusRoutine])) \
+ ((BusNumber), (pSlaveTransfer), (TranslatedBufferAddress))
+
+#define ArcEisaReleaseCpuAccessToEisaBus(BusNumber, pSlaveTransfer, TranslatedBufferAddress) \
+ ((PEISA_RELEASE_CPU_TO_BUS_ACCESS_RTN)(SYSTEM_BLOCK->Adapter0Vector[ReleaseCpuAccessToBusRoutine])) \
+ ((BusNumber), (pSlaveTransfer), (TranslatedBufferAddress))
+
+#define ArcEisaFlushCache(Address, Length) \
+ ((PEISA_FLUSH_CACHE_RTN)(SYSTEM_BLOCK->Adapter0Vector[FlushCacheRoutine])) \
+ ((Address), (Length))
+
+#define ArcEisaInvalidateCache(Address, Length) \
+ ((PEISA_INVALIDATE_CACHE_RTN)(SYSTEM_BLOCK->Adapter0Vector[InvalidateCacheRoutine])) \
+ ((Address), (Length))
+
+#define ArcEisaBeginCriticalSection() \
+ ((PEISA_BEGIN_CRITICAL_SECTION_RTN)(SYSTEM_BLOCK->Adapter0Vector[BeginCriticalSectionRoutine]))()
+
+#define ArcEisaEndCriticalSection() \
+ ((PEISA_END_CRITICAL_SECTION_RTN)(SYSTEM_BLOCK->Adapter0Vector[EndCriticalSectionRoutine]))()
+
+#define ArcEisaGenerateTone() \
+ ((PEISA_GENERATE_TONE_RTN)(SYSTEM_BLOCK->Adapter0Vector[GenerateToneRoutine])) \
+ ((Freqency), (Duration))
+
+#define ArcEisaFlushWriteBuffers() \
+ ((PEISA_FLUSH_WRITE_BUFFER_RTN)(SYSTEM_BLOCK->Adapter0Vector[FlushWriteBuffersRoutine]))()
+
+#define ArcEisaYield() \
+ ((PEISA_YIELD_RTN)(SYSTEM_BLOCK->Adapter0Vector[YieldRoutine]))()
+
+#define ArcEisaStallProcessor(Duration) \
+ ((PEISA_STALL_PROCESSOR_RTN)(SYSTEM_BLOCK->Adapter0Vector[StallProcessorRoutine])) \
+ (Duration)
+
+
+//
+// General OMF defines
+//
+
+#define OMF_BLOCK_SIZE 512 // OMF block size in bytes
+#define OMF_MAX_SIZE (32*1024*1024) // max OMF size in bytes
+#define OMF_MAX_FILE_LEN ((16*1024*1024)/(1<<WORD_2P2)) // (16 Mbytes max)/4
+#define OMF_MAX_FILE_LINK ((16*1024*1024)/(1<<WORD_2P2)) // (16 Mbytes max)/4
+#define OMF_ID_1ST 0x55 // 1st OMF ID
+#define OMF_ID_2ND 0x00 // 2nd OMF ID
+#define OMF_ID_3RD 0xAA // 3rd OMF ID
+#define OMF_ID_4TH 0xFF // 4th OMF ID
+#define OMF_FILE_NAME_LEN 12 // 12 chars
+
+//
+// Define OMF FAT file name structure
+//
+typedef struct _OMF_FAT_FILE_NAME
+ {
+ CHAR ProductId[7];
+ CHAR Version;
+ CHAR Dot;
+ CHAR Extension[2];
+ CHAR Revision;
+ } OMF_FAT_FILE_NAME, *POMF_FAT_FILE_NAME;
+
diff --git a/private/ntos/fw/alpha/ati.h b/private/ntos/fw/alpha/ati.h
new file mode 100644
index 000000000..59534c0fd
--- /dev/null
+++ b/private/ntos/fw/alpha/ati.h
@@ -0,0 +1,389 @@
+//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+//;;;;;
+//;; Filename: 68800.asm
+//;; Copyright (c) 1989, ATI Technologies Inc.
+//;; Copyright (c) 1993 Digital Equipment Corporation.
+//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+//;;;;;;
+// $Revision: 1.2 $
+// $Date: 20 Jul 1989 16:19:06 $
+// $Author: Peter Liepa $
+// $Log: J:\video\vga1\inc\vcs\68800.asv
+//
+// Rev 1.2 20 Jul 1989 16:19:06 Pet
+// cosmetic changes to conform to project
+//*************************************************************************
+//** **
+//** 68800.INC **
+//** **
+//** Copyright (c) 1989, ATI Technologies Inc. **
+//*************************************************************************
+//
+//
+// $Revision: 1.0 $
+// $Date: 01 Jul 1992 10:28:58 $
+// $Author: 8514GRP $
+// $Log: D:/mach32/vcs/68800.inv $
+//
+// Rev 1.0 01 Jul 1992 10:28:58 8514GRP
+// Build 30:
+// - created the 68800.inc file which includes equates, macros, etc
+// from the following include files: - 8514vesa.inc
+// - vga1regs.inc
+// - m32regs.inc
+// - 8514.inc
+// (these include files are no longer required)
+// - the 8514regs.inc file is now eliminated
+// - the makefile has been updated accordingly
+//
+//
+// 31-March-93 Bruce Butts [DEC]
+//
+// Converted hardcoded QVA definitions to generic QVA macros.
+//
+#include "machdef.h"
+//
+//-------------------------------------------------------------------------
+// REGISTER PORT ADDRESSES
+//
+
+#define TI_DAC 4
+#define ATT_DAC 8
+#define DAC_MASK EisaIOQva(0x02EA) // DAC Mask-
+#define INPUT_CLK_SEL EisaIOQva(0x02ed)
+#define OUTPUT_CLK_SEL EisaIOQva(0x02ea)
+#define MUX_CNTL EisaIOQva(0x02eb)
+#define LOCAL_CNTL EisaIOQva(0x32ee)
+#define HORIZONTAL_OVERSCAN EisaIOQva(0x62EE)
+#define ATT_MODE_CNTL EisaIOQva(0x02ea)
+#define ADVFUNC_CNTL EisaIOQva(0x4AE8) // Advanced Function Control
+#define CLOCK_SEL EisaIOQva(0x4AEE)
+#define CONFIG_STATUS_1 EisaIOQva(0x12EE) // Read only equivalent to HORZ_CURSOR_POSN
+#define DISP_CNTL EisaIOQva(0x22E8) // Display Control
+#define EXT_GE_CONFIG EisaIOQva(0x7AEE)
+#define MISC_CNTL EisaIOQva(0x7EEE)
+#define R_MISC_CNTL EisaIOQva(0x92EE)
+
+
+
+#if 0
+
+//
+// These ATI definitions are not believed to be needed.
+//
+
+#define SETUP_ID1 0x0100 // Setup Mode Identification (Byte 1)
+#define SETUP_ID2 0x0101 // Setup Mode Identification (Byte 2)
+#define SETUP_OPT 0x0102 // Setup Mode Option Select
+#define ROM_SETUP 0x0103 //
+#define SETUP_1 0x0104 //
+#define SETUP_2 0x0105 //
+#define DISP_STATUS 0x02E8 // Display Status
+#define H_TOTAL 0x02E8 // Horizontal Total
+#define DAC_R_INDEX 0x02EB // DAC Read Index
+#define DAC_W_INDEX 0x02EC // DAC Write Index
+#define DAC_DATA 0x02ED // DAC Data
+#define OVERSCAN_COLOR_8 0x02EE
+#define OVERSCAN_BLUE_24 0x02EF
+#define H_DISP 0x06E8 // Horizontal Displayed
+#define OVERSCAN_GREEN_24 0x06EE
+#define OVERSCAN_RED_24 0x06EF
+#define H_SYNC_STRT 0x0AE8 // Horizontal Sync Start
+#define CURSOR_OFFSET_LO 0x0AEE
+#define H_SYNC_WID 0x0EE8 // Horizontal Sync Width
+#define CURSOR_OFFSET_HI 0x0EEE
+#define V_TOTAL 0x12E8 // Vertical Total
+#define HORZ_CURSOR_POSN 0x12EE
+#define V_DISP 0x16E8 // Vertical Displayed
+#define CONFIG_STATUS_2 0x16EE // Read only equivalent to VERT_CURSOR_POSN
+#define VERT_CURSOR_POSN 0x16EE
+#define V_SYNC_STRT 0x1AE8 // Vertical Sync Start
+#define CURSOR_COLOR_0 0x1AEE
+#define FIFO_TEST_DATA 0x1AEE
+#define CURSOR_COLOR_1 0x1AEF
+#define V_SYNC_WID 0x1EE8 // Vertical Sync Width
+#define HORZ_CURSOR_OFFSET 0x1EEE
+#define VERT_CURSOR_OFFSET 0x1EEF
+#define CRT_PITCH 0x26EE
+#define CRT_OFFSET_LO 0x2AEE
+#define CRT_OFFSET_HI 0x2EEE
+#define LOCAL_CONTROL 0x32EE
+#define FIFO_OPT 0x36EE
+#define MISC_OPTIONS 0x36EE
+#define EXT_CURSOR_COLOR_0 0x3AEE
+#define FIFO_TEST_TAG 0x3AEE
+#define EXT_CURSOR_COLOR_1 0x3EEE
+#define SUBSYS_CNTL 0x42E8 // Subsystem Control
+#define SUBSYS_STAT 0x42E8 // Subsystem Status
+#define MEM_BNDRY 0x42EE
+#define SHADOW_CTL 0x46EE
+#define ROM_PAGE_SEL 0x46E8 // ROM Page Select (not in manual)
+#define SCRATCH_PAD_0 0x52EE
+#define SCRATCH_PAD_1 0x56EE
+#define SHADOW_SET 0x5AEE
+#define MEM_CFG 0x5EEE
+#define EXT_GE_STATUS 0x62EE
+#define HORZ_OVERSCAN 0x62EE
+#define VERT_OVERSCAN 0x66EE
+#define MAX_WAITSTATES 0x6AEE
+#define GE_OFFSET_LO 0x6EEE
+#define BOUNDS_LEFT 0x72EE
+#define GE_OFFSET_HI 0x72EE
+#define BOUNDS_TOP 0x76EE
+#define GE_PITCH 0x76EE
+#define BOUNDS_RIGHT 0x7AEE
+#define BOUNDS_BOTTOM 0x7EEE
+#define CUR_Y 0x82E8 // Current Y Position
+#define PATT_DATA_INDEX 0x82EE
+#define CUR_X 0x86E8 // Current X Position
+#define SRC_Y 0x8AE8 //
+#define DEST_Y 0x8AE8 //
+#define AXSTP 0x8AE8 // Destination Y Position
+// Axial Step Constant
+#define SRC_X 0x8EE8 //
+#define DEST_X 0x8EE8 //
+#define DIASTP 0x8EE8 // Destination X Position
+// Diagonial Step Constant
+#define PATT_DATA 0x8EEE
+#define R_EXT_GE_CONFIG 0x8EEE
+#define ERR_TERM 0x92E8 // Error Term
+#define MAJ_AXIS_PCNT 0x96E8 // Major Axis Pixel Count
+#define BRES_COUNT 0x96EE
+#define CMD 0x9AE8 // Command
+#define GE_STAT 0x9AE8 // Graphics Processor Status
+#define EXT_FIFO_STATUS 0x9AEE
+#define LINEDRAW_INDEX 0x9AEE
+#define SHORT_STROKE 0x9EE8 // Short Stroke Vector Transfer
+#define BKGD_COLOR 0xA2E8 // Background Color
+#define LINEDRAW_OPT 0xA2EE
+#define FRGD_COLOR 0xA6E8 // Foreground Color
+#define DEST_X_START 0xA6EE
+#define WRT_MASK 0xAAE8 // Write Mask
+#define DEST_X_END 0xAAEE
+#define RD_MASK 0xAEE8 // Read Mask
+#define DEST_Y_END 0xAEEE
+#define CMP_COLOR 0xB2E8 // Compare Color
+#define R_H_TOTAL 0xB2EE
+#define R_H_DISP 0xB2EE
+#define SRC_X_START 0xB2EE
+#define BKGD_MIX 0xB6E8 // Background Mix
+#define ALU_BG_FN 0xB6EE
+#define R_H_SYNC_STRT 0xB6EE
+#define FRGD_MIX 0xBAE8 // Foreground Mix
+#define ALU_FG_FN 0xBAEE
+#define R_H_SYNC_WID 0xBAEE
+#define MULTIFUNC_CNTL 0xBEE8 // Multi-Function Control (mach 8)
+#define MIN_AXIS_PCNT 0xBEE8
+#define SCISSOR_T 0xBEE8
+#define SCISSOR_L 0xBEE8
+#define SCISSOR_B 0xBEE8
+#define SCISSOR_R 0xBEE8
+#define MEM_CNTL 0xBEE8
+#define PATTERN_L 0xBEE8
+#define PATTERN_H 0xBEE8
+#define PIXEL_CNTL 0xBEE8
+#define SRC_X_END 0xBEEE
+#define SRC_Y_DIR 0xC2EE
+#define R_V_TOTAL 0xC2EE
+#define EXT_SSV 0xC6EE // (used for MACH 8)
+#define EXT_SHORT_STROKE 0xC6EE
+#define R_V_DISP 0xC6EE
+#define SCAN_X 0xCAEE
+#define R_V_SYNC_STRT 0xCAEE
+#define DP_CONFIG 0xCEEE
+#define VERT_LINE_CNTR 0xCEEE
+#define PATT_LENGTH 0xD2EE
+#define R_V_SYNC_WID 0xD2EE
+#define PATT_INDEX 0xD6EE
+#define EXT_SCISSOR_L 0xDAEE // "extended" left scissor (12 bits precision)
+#define R_SRC_X 0xDAEE
+#define EXT_SCISSOR_T 0xDEEE // "extended" top scissor (12 bits precision)
+#define R_SRC_Y 0xDEEE
+#define PIX_TRANS 0xE2E8 // Pixel Data Transfer
+#define EXT_SCISSOR_R 0xE2EE // "extended" right scissor (12 bits precision)
+#define EXT_SCISSOR_B 0xE6EE // "extended" bottom scissor (12 bits precision)
+#define SRC_CMP_COLOR 0xEAEE // (used for MACH 8)
+#define DEST_CMP_FN 0xEEEE
+#define LINEDRAW 0xFEEE
+//---------------------------------------------------------
+// macros (from 8514.inc)
+//
+// I/O macros:
+//
+//mov if port NOT = to DX
+//
+//mov if port NOT = to DX
+//
+//
+//
+//Following are the FIFO checking macros:
+//
+//
+//
+//FIFO space check macro:
+//
+#define ONE_WORD 0x8000
+#define TWO_WORDS 0xC000
+#define THREE_WORDS 0xE000
+#define FOUR_WORDS 0xF000
+#define FIVE_WORDS 0xF800
+#define SIX_WORDS 0xFC00
+#define SEVEN_WORDS 0xFE00
+#define EIGHT_WORDS 0xFF00
+#define NINE_WORDS 0xFF80
+#define TEN_WORDS 0xFFC0
+#define ELEVEN_WORDS 0xFFE0
+#define TWELVE_WORDS 0xFFF0
+#define THIRTEEN_WORDS 0xFFF8
+#define FOURTEEN_WORDS 0xFFFC
+#define FIFTEEN_WORDS 0xFFFE
+#define SIXTEEN_WORDS 0xFFFF
+//
+//
+//
+//---------------------------------------
+//
+//
+// Draw Command (DRAW_COMMAND) (from 8514regs.inc)
+// note: required by m32poly.asm
+//
+// opcode field
+#define OP_CODE 0xE000
+#define SHIFT_op_code 0x000D
+#define DRAW_SETUP 0x0000
+#define DRAW_LINE 0x2000
+#define FILL_RECT_H1H4 0x4000
+#define FILL_RECT_V1V2 0x6000
+#define FILL_RECT_V1H4 0x8000
+#define DRAW_POLY_LINE 0xA000
+#define BITBLT_OP 0xC000
+#define DRAW_FOREVER 0xE000
+// swap field
+#define LSB_FIRST 0x1000
+// data width field
+#define DATA_WIDTH 0x0200
+#define BIT16 0x0200
+#define BIT8 0x0000
+// CPU wait field
+#define CPU_WAIT 0x0100
+// octant field
+#define OCTANT 0x00E0
+#define SHIFT_octant 0x0005
+#define YPOSITIVE 0x0080
+#define YMAJOR 0x0040
+#define XPOSITIVE 0x0020
+// draw field
+#define DRAW 0x0010
+// direction field
+#define DIR_TYPE 0x0008
+#define DEGREE 0x0008
+#define XY 0x0000
+#define RECT_RIGHT_AND_DOWN 0x00E0 // quadrant 3
+#define RECT_LEFT_AND_UP 0x0000 // quadrant 1
+// last pel off field
+#define SHIFT_last_pel_off 0x0002
+#define LAST_PEL_OFF 0x0004
+#define LAST_PEL_ON 0x0000
+// pixel mode
+#define PIXEL_MODE 0x0002
+#define MULTI 0x0002
+#define SINGLE 0x0000
+// read/write
+#define RW 0x0001
+#define WRITE 0x0001
+#define READ 0x0000
+//
+// ---------------------------------------------------------
+// 8514 register definitions (from vga1regs.inc)
+//
+// Internal registers (read only, for test purposes only)
+#define _PAR_FIFO_DATA 0x1AEE
+#define _PAR_FIFO_ADDR 0x3AEE
+#define _MAJOR_DEST_CNT 0x42EE
+#define _MAJOR_SRC_CNT 0x5EEE
+#define _MINOR_DEST_CNT 0x66EE
+#define _MINOR_SRC_CNT 0x8AEE
+#define _HW_TEST 0x32EE
+//
+// Extended Graphics Engine Status (EXT_GE_STATUS)
+// -rn- used in mach32.asm
+//
+#define POINTS_INSIDE 0x8000
+#define EE_DATA_IN 0x4000
+#define GE_ACTIVE 0x2000
+#define CLIP_ABOVE 0x1000
+#define CLIP_BELOW 0x0800
+#define CLIP_LEFT 0x0400
+#define CLIP_RIGHT 0x0200
+#define CLIP_FLAGS 0x1E00
+#define CLIP_INSIDE 0x0100
+#define EE_CRC_VALID 0x0080
+#define CLIP_OVERRUN 0x000F
+//
+// Datapath Configuration Register (DP_CONFIG)
+// note: some of the EQU is needed in m32poly.asm
+#define FG_COLOR_SRC 0xE000
+#define SHIFT_fg_color_src 0x000D
+#define DATA_ORDER 0x1000
+#define DATA_WIDTH 0x0200
+#define BG_COLOR_SRC 0x0180
+#define SHIFT_bg_color_src 0x0007
+#define EXT_MONO_SRC 0x0060
+#define SHIFT_ext_mono_src 0x0005
+#define DRAW 0x0010
+#define READ_MODE 0x0004
+#define POLY_FILL_MODE 0x0002
+#define SRC_SWAP 0x0800
+//
+#define FG_COLOR_SRC_BG 0x0000 // Background Color Register
+#define FG_COLOR_SRC_FG 0x2000 // Foreground Color Register
+#define FG_COLOR_SRC_HOST 0x4000 // CPU Data Transfer Reg
+#define FG_COLOR_SRC_BLIT 0x6000 // VRAM blit source
+#define FG_COLOR_SRC_GS 0x8000 // Grey-scale mono blit
+#define FG_COLOR_SRC_PATT 0xA000 // Color Pattern Shift Reg
+#define FG_COLOR_SRC_CLUH 0xC000 // Color lookup of Host Data
+#define FG_COLOR_SRC_CLUB 0xE000 // Color lookup of blit src
+//
+#define BG_COLOR_SRC_BG 0x0000 // Background Color Reg
+#define BG_COLOR_SRC_FG 0x0080 // Foreground Color Reg
+#define BG_COLOR_SRC_HOST 0x0100 // CPU Data Transfer Reg
+#define BG_COLOR_SRC_BLIT 0x0180 // VRAM blit source
+//
+// Note that "EXT_MONO_SRC" and "MONO_SRC" are mutually destructive, but that
+// "EXT_MONO_SRC" selects the ATI pattern registers.
+//
+#define EXT_MONO_SRC_ONE 0x0000 // Always '1'
+#define EXT_MONO_SRC_PATT 0x0020 // ATI Mono Pattern Regs
+#define EXT_MONO_SRC_HOST 0x0040 // CPU Data Transfer Reg
+#define EXT_MONO_SRC_BLIT 0x0060 // VRAM Blit source plane
+//
+// Linedraw Options Register (LINEDRAW_OPT)
+//
+// note: some of the EQUS are needed in m32poly.asm
+#define CLIP_MODE 0x0600
+#define SHIFT_clip_mode 0x0009
+#define CLIP_MODE_DIS 0x0000
+#define CLIP_MODE_LINE 0x0200
+#define CLIP_MODE_PLINE 0x0400
+#define CLIP_MODE_PATT 0x0600
+#define BOUNDS_RESET 0x0100
+#define OCTANT 0x00E0
+#define SHIFT_ldo_octant 0x0005
+#define YDIR 0x0080
+#define XMAJOR 0x0040
+#define XDIR 0x0020
+#define DIR_TYPE 0x0008
+#define DIR_TYPE_DEGREE 0x0008
+#define DIR_TYPE_OCTANT 0x0000
+#define LAST_PEL_OFF 0x0004
+#define POLY_MODE 0x0002
+//
+//
+// ------------------------------------------------------------
+// Mach32 register equates (from m32regs.inc)
+//
+#define REVISION 0x0000
+//HORIZONTAL_OVERSCAN equ 062EEh
+//VERTICAL_OVERSCAN equ 066EEh
+
+#endif
diff --git a/private/ntos/fw/alpha/atidisk/68800.h b/private/ntos/fw/alpha/atidisk/68800.h
new file mode 100644
index 000000000..44ae5ba2b
--- /dev/null
+++ b/private/ntos/fw/alpha/atidisk/68800.h
@@ -0,0 +1,362 @@
+//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+//;;;;;
+//;; Filename: 68800.asm
+//;; Copyright (c) 1989, ATI Technologies Inc.
+//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+//;;;;;;
+// $Revision: 1.2 $
+// $Date: 20 Jul 1989 16:19:06 $
+// $Author: Peter Liepa $
+// $Log: J:\video\vga1\inc\vcs\68800.asv
+//
+// Rev 1.2 20 Jul 1989 16:19:06 Pet
+// cosmetic changes to conform to project
+//*************************************************************************
+//** **
+//** 68800.INC **
+//** **
+//** Copyright (c) 1989, ATI Technologies Inc. **
+//*************************************************************************
+//
+//
+// $Revision: 1.0 $
+// $Date: 01 Jul 1992 10:28:58 $
+// $Author: 8514GRP $
+// $Log: D:/mach32/vcs/68800.inv $
+//
+// Rev 1.0 01 Jul 1992 10:28:58 8514GRP
+// Build 30:
+// - created the 68800.inc file which includes equates, macros, etc
+// from the following include files: - 8514vesa.inc
+// - vga1regs.inc
+// - m32regs.inc
+// - 8514.inc
+// (these include files are no longer required)
+// - the 8514regs.inc file is now eliminated
+// - the makefile has been updated accordingly
+//
+//
+//-------------------------------------------------------------------------
+// REGISTER PORT ADDRESSES
+//
+#define SETUP_ID1 0x0100 // Setup Mode Identification (Byte 1)
+#define SETUP_ID2 0x0101 // Setup Mode Identification (Byte 2)
+#define SETUP_OPT 0x0102 // Setup Mode Option Select
+#define ROM_SETUP 0x0103 //
+#define SETUP_1 0x0104 //
+#define SETUP_2 0x0105 //
+#define DISP_STATUS 0x02E8 // Display Status
+#define H_TOTAL 0x02E8 // Horizontal Total
+#define DAC_MASK 0x02EA // DAC Mask
+#define DAC_R_INDEX 0x02EB // DAC Read Index
+#define DAC_W_INDEX 0x02EC // DAC Write Index
+#define DAC_DATA 0x02ED // DAC Data
+#define OVERSCAN_COLOR_8 0x02EE
+#define OVERSCAN_BLUE_24 0x02EF
+#define H_DISP 0x06E8 // Horizontal Displayed
+#define OVERSCAN_GREEN_24 0x06EE
+#define OVERSCAN_RED_24 0x06EF
+#define H_SYNC_STRT 0x0AE8 // Horizontal Sync Start
+#define CURSOR_OFFSET_LO 0x0AEE
+#define H_SYNC_WID 0x0EE8 // Horizontal Sync Width
+#define CURSOR_OFFSET_HI 0x0EEE
+#define V_TOTAL 0x12E8 // Vertical Total
+#define CONFIG_STATUS_1 0x12EE // Read only equivalent to HORZ_CURSOR_POSN
+#define HORZ_CURSOR_POSN 0x12EE
+#define V_DISP 0x16E8 // Vertical Displayed
+#define CONFIG_STATUS_2 0x16EE // Read only equivalent to VERT_CURSOR_POSN
+#define VERT_CURSOR_POSN 0x16EE
+#define V_SYNC_STRT 0x1AE8 // Vertical Sync Start
+#define CURSOR_COLOR_0 0x1AEE
+#define FIFO_TEST_DATA 0x1AEE
+#define CURSOR_COLOR_1 0x1AEF
+#define V_SYNC_WID 0x1EE8 // Vertical Sync Width
+#define HORZ_CURSOR_OFFSET 0x1EEE
+#define VERT_CURSOR_OFFSET 0x1EEF
+#define DISP_CNTL 0x22E8 // Display Control
+#define CRT_PITCH 0x26EE
+#define CRT_OFFSET_LO 0x2AEE
+#define CRT_OFFSET_HI 0x2EEE
+#define LOCAL_CONTROL 0x32EE
+#define FIFO_OPT 0x36EE
+#define MISC_OPTIONS 0x36EE
+#define EXT_CURSOR_COLOR_0 0x3AEE
+#define FIFO_TEST_TAG 0x3AEE
+#define EXT_CURSOR_COLOR_1 0x3EEE
+#define SUBSYS_CNTL 0x42E8 // Subsystem Control
+#define SUBSYS_STAT 0x42E8 // Subsystem Status
+#define MEM_BNDRY 0x42EE
+#define SHADOW_CTL 0x46EE
+#define ROM_PAGE_SEL 0x46E8 // ROM Page Select (not in manual)
+#define ADVFUNC_CNTL 0x4AE8 // Advanced Function Control
+#define CLOCK_SEL 0x4AEE
+#define SCRATCH_PAD_0 0x52EE
+#define SCRATCH_PAD_1 0x56EE
+#define SHADOW_SET 0x5AEE
+#define MEM_CFG 0x5EEE
+#define EXT_GE_STATUS 0x62EE
+#define HORZ_OVERSCAN 0x62EE
+#define VERT_OVERSCAN 0x66EE
+#define MAX_WAITSTATES 0x6AEE
+#define GE_OFFSET_LO 0x6EEE
+#define BOUNDS_LEFT 0x72EE
+#define GE_OFFSET_HI 0x72EE
+#define BOUNDS_TOP 0x76EE
+#define GE_PITCH 0x76EE
+#define BOUNDS_RIGHT 0x7AEE
+#define EXT_GE_CONFIG 0x7AEE
+#define BOUNDS_BOTTOM 0x7EEE
+#define MISC_CNTL 0x7EEE
+#define CUR_Y 0x82E8 // Current Y Position
+#define PATT_DATA_INDEX 0x82EE
+#define CUR_X 0x86E8 // Current X Position
+#define SRC_Y 0x8AE8 //
+#define DEST_Y 0x8AE8 //
+#define AXSTP 0x8AE8 // Destination Y Position
+// Axial Step Constant
+#define SRC_X 0x8EE8 //
+#define DEST_X 0x8EE8 //
+#define DIASTP 0x8EE8 // Destination X Position
+// Diagonial Step Constant
+#define PATT_DATA 0x8EEE
+#define R_EXT_GE_CONFIG 0x8EEE
+#define ERR_TERM 0x92E8 // Error Term
+#define R_MISC_CNTL 0x92EE
+#define MAJ_AXIS_PCNT 0x96E8 // Major Axis Pixel Count
+#define BRES_COUNT 0x96EE
+#define CMD 0x9AE8 // Command
+#define GE_STAT 0x9AE8 // Graphics Processor Status
+#define EXT_FIFO_STATUS 0x9AEE
+#define LINEDRAW_INDEX 0x9AEE
+#define SHORT_STROKE 0x9EE8 // Short Stroke Vector Transfer
+#define BKGD_COLOR 0xA2E8 // Background Color
+#define LINEDRAW_OPT 0xA2EE
+#define FRGD_COLOR 0xA6E8 // Foreground Color
+#define DEST_X_START 0xA6EE
+#define WRT_MASK 0xAAE8 // Write Mask
+#define DEST_X_END 0xAAEE
+#define RD_MASK 0xAEE8 // Read Mask
+#define DEST_Y_END 0xAEEE
+#define CMP_COLOR 0xB2E8 // Compare Color
+#define R_H_TOTAL 0xB2EE
+#define R_H_DISP 0xB2EE
+#define SRC_X_START 0xB2EE
+#define BKGD_MIX 0xB6E8 // Background Mix
+#define ALU_BG_FN 0xB6EE
+#define R_H_SYNC_STRT 0xB6EE
+#define FRGD_MIX 0xBAE8 // Foreground Mix
+#define ALU_FG_FN 0xBAEE
+#define R_H_SYNC_WID 0xBAEE
+#define MULTIFUNC_CNTL 0xBEE8 // Multi-Function Control (mach 8)
+#define MIN_AXIS_PCNT 0xBEE8
+#define SCISSOR_T 0xBEE8
+#define SCISSOR_L 0xBEE8
+#define SCISSOR_B 0xBEE8
+#define SCISSOR_R 0xBEE8
+#define MEM_CNTL 0xBEE8
+#define PATTERN_L 0xBEE8
+#define PATTERN_H 0xBEE8
+#define PIXEL_CNTL 0xBEE8
+#define SRC_X_END 0xBEEE
+#define SRC_Y_DIR 0xC2EE
+#define R_V_TOTAL 0xC2EE
+#define EXT_SSV 0xC6EE // (used for MACH 8)
+#define EXT_SHORT_STROKE 0xC6EE
+#define R_V_DISP 0xC6EE
+#define SCAN_X 0xCAEE
+#define R_V_SYNC_STRT 0xCAEE
+#define DP_CONFIG 0xCEEE
+#define VERT_LINE_CNTR 0xCEEE
+#define PATT_LENGTH 0xD2EE
+#define R_V_SYNC_WID 0xD2EE
+#define PATT_INDEX 0xD6EE
+#define EXT_SCISSOR_L 0xDAEE // "extended" left scissor (12 bits precision)
+#define R_SRC_X 0xDAEE
+#define EXT_SCISSOR_T 0xDEEE // "extended" top scissor (12 bits precision)
+#define R_SRC_Y 0xDEEE
+#define PIX_TRANS 0xE2E8 // Pixel Data Transfer
+#define EXT_SCISSOR_R 0xE2EE // "extended" right scissor (12 bits precision)
+#define EXT_SCISSOR_B 0xE6EE // "extended" bottom scissor (12 bits precision)
+#define SRC_CMP_COLOR 0xEAEE // (used for MACH 8)
+#define DEST_CMP_FN 0xEEEE
+#define LINEDRAW 0xFEEE
+//---------------------------------------------------------
+// macros (from 8514.inc)
+//
+// I/O macros:
+//
+//mov if port NOT = to DX
+//
+//mov if port NOT = to DX
+//
+//
+//
+//Following are the FIFO checking macros:
+//
+//
+//
+//FIFO space check macro:
+//
+#define ONE_WORD 0x8000
+#define TWO_WORDS 0xC000
+#define THREE_WORDS 0xE000
+#define FOUR_WORDS 0xF000
+#define FIVE_WORDS 0xF800
+#define SIX_WORDS 0xFC00
+#define SEVEN_WORDS 0xFE00
+#define EIGHT_WORDS 0xFF00
+#define NINE_WORDS 0xFF80
+#define TEN_WORDS 0xFFC0
+#define ELEVEN_WORDS 0xFFE0
+#define TWELVE_WORDS 0xFFF0
+#define THIRTEEN_WORDS 0xFFF8
+#define FOURTEEN_WORDS 0xFFFC
+#define FIFTEEN_WORDS 0xFFFE
+#define SIXTEEN_WORDS 0xFFFF
+//
+//
+//
+//---------------------------------------
+//
+//
+// Draw Command (DRAW_COMMAND) (from 8514regs.inc)
+// note: required by m32poly.asm
+//
+// opcode field
+#define OP_CODE 0xE000
+#define SHIFT_op_code 0x000D
+#define DRAW_SETUP 0x0000
+#define DRAW_LINE 0x2000
+#define FILL_RECT_H1H4 0x4000
+#define FILL_RECT_V1V2 0x6000
+#define FILL_RECT_V1H4 0x8000
+#define DRAW_POLY_LINE 0xA000
+#define BITBLT_OP 0xC000
+#define DRAW_FOREVER 0xE000
+// swap field
+#define LSB_FIRST 0x1000
+// data width field
+#define DATA_WIDTH 0x0200
+#define BIT16 0x0200
+#define BIT8 0x0000
+// CPU wait field
+#define CPU_WAIT 0x0100
+// octant field
+#define OCTANT 0x00E0
+#define SHIFT_octant 0x0005
+#define YPOSITIVE 0x0080
+#define YMAJOR 0x0040
+#define XPOSITIVE 0x0020
+// draw field
+#define DRAW 0x0010
+// direction field
+#define DIR_TYPE 0x0008
+#define DEGREE 0x0008
+#define XY 0x0000
+#define RECT_RIGHT_AND_DOWN 0x00E0 // quadrant 3
+#define RECT_LEFT_AND_UP 0x0000 // quadrant 1
+// last pel off field
+#define SHIFT_last_pel_off 0x0002
+#define LAST_PEL_OFF 0x0004
+#define LAST_PEL_ON 0x0000
+// pixel mode
+#define PIXEL_MODE 0x0002
+#define MULTI 0x0002
+#define SINGLE 0x0000
+// read/write
+#define RW 0x0001
+#define WRITE 0x0001
+#define READ 0x0000
+//
+// ---------------------------------------------------------
+// 8514 register definitions (from vga1regs.inc)
+//
+// Internal registers (read only, for test purposes only)
+#define _PAR_FIFO_DATA 0x1AEE
+#define _PAR_FIFO_ADDR 0x3AEE
+#define _MAJOR_DEST_CNT 0x42EE
+#define _MAJOR_SRC_CNT 0x5EEE
+#define _MINOR_DEST_CNT 0x66EE
+#define _MINOR_SRC_CNT 0x8AEE
+#define _HW_TEST 0x32EE
+//
+// Extended Graphics Engine Status (EXT_GE_STATUS)
+// -rn- used in mach32.asm
+//
+#define POINTS_INSIDE 0x8000
+#define EE_DATA_IN 0x4000
+#define GE_ACTIVE 0x2000
+#define CLIP_ABOVE 0x1000
+#define CLIP_BELOW 0x0800
+#define CLIP_LEFT 0x0400
+#define CLIP_RIGHT 0x0200
+#define CLIP_FLAGS 0x1E00
+#define CLIP_INSIDE 0x0100
+#define EE_CRC_VALID 0x0080
+#define CLIP_OVERRUN 0x000F
+//
+// Datapath Configuration Register (DP_CONFIG)
+// note: some of the EQU is needed in m32poly.asm
+#define FG_COLOR_SRC 0xE000
+#define SHIFT_fg_color_src 0x000D
+#define DATA_ORDER 0x1000
+#define DATA_WIDTH 0x0200
+#define BG_COLOR_SRC 0x0180
+#define SHIFT_bg_color_src 0x0007
+#define EXT_MONO_SRC 0x0060
+#define SHIFT_ext_mono_src 0x0005
+#define DRAW 0x0010
+#define READ_MODE 0x0004
+#define POLY_FILL_MODE 0x0002
+#define SRC_SWAP 0x0800
+//
+#define FG_COLOR_SRC_BG 0x0000 // Background Color Register
+#define FG_COLOR_SRC_FG 0x2000 // Foreground Color Register
+#define FG_COLOR_SRC_HOST 0x4000 // CPU Data Transfer Reg
+#define FG_COLOR_SRC_BLIT 0x6000 // VRAM blit source
+#define FG_COLOR_SRC_GS 0x8000 // Grey-scale mono blit
+#define FG_COLOR_SRC_PATT 0xA000 // Color Pattern Shift Reg
+#define FG_COLOR_SRC_CLUH 0xC000 // Color lookup of Host Data
+#define FG_COLOR_SRC_CLUB 0xE000 // Color lookup of blit src
+//
+#define BG_COLOR_SRC_BG 0x0000 // Background Color Reg
+#define BG_COLOR_SRC_FG 0x0080 // Foreground Color Reg
+#define BG_COLOR_SRC_HOST 0x0100 // CPU Data Transfer Reg
+#define BG_COLOR_SRC_BLIT 0x0180 // VRAM blit source
+//
+// Note that "EXT_MONO_SRC" and "MONO_SRC" are mutually destructive, but that
+// "EXT_MONO_SRC" selects the ATI pattern registers.
+//
+#define EXT_MONO_SRC_ONE 0x0000 // Always '1'
+#define EXT_MONO_SRC_PATT 0x0020 // ATI Mono Pattern Regs
+#define EXT_MONO_SRC_HOST 0x0040 // CPU Data Transfer Reg
+#define EXT_MONO_SRC_BLIT 0x0060 // VRAM Blit source plane
+//
+// Linedraw Options Register (LINEDRAW_OPT)
+//
+// note: some of the EQUS are needed in m32poly.asm
+#define CLIP_MODE 0x0600
+#define SHIFT_clip_mode 0x0009
+#define CLIP_MODE_DIS 0x0000
+#define CLIP_MODE_LINE 0x0200
+#define CLIP_MODE_PLINE 0x0400
+#define CLIP_MODE_PATT 0x0600
+#define BOUNDS_RESET 0x0100
+#define OCTANT 0x00E0
+#define SHIFT_ldo_octant 0x0005
+#define YDIR 0x0080
+#define XMAJOR 0x0040
+#define XDIR 0x0020
+#define DIR_TYPE 0x0008
+#define DIR_TYPE_DEGREE 0x0008
+#define DIR_TYPE_OCTANT 0x0000
+#define LAST_PEL_OFF 0x0004
+#define POLY_MODE 0x0002
+//
+//
+// ------------------------------------------------------------
+// Mach32 register equates (from m32regs.inc)
+//
+#define REVISION 0x0000
+//HORIZONTAL_OVERSCAN equ 062EEh
+//VERTICAL_OVERSCAN equ 066EEh
diff --git a/private/ntos/fw/alpha/atidisk/sample.txt b/private/ntos/fw/alpha/atidisk/sample.txt
new file mode 100644
index 000000000..ad0662be6
--- /dev/null
+++ b/private/ntos/fw/alpha/atidisk/sample.txt
@@ -0,0 +1,131 @@
+
+#define ATI68830_DAC 0
+#define SIERRA_DAC 2
+#define TI_DAC 4
+#define BROOKTREE_DAC 6
+#define ATT_DAC 8
+#define INPUT_CLK_SEL 0x2ed
+#define OUTPUT_CLK_SEL 0x2ea
+#define MUX_CNTL 0x2eb
+#define HORIZONTAL_OVERSCAN 0x62EE
+#define ATT_MODE_CNTL 0x2ea
+#define LOCAL_CNTL 0x32ee
+#define NUM_ROM_BASE_RANGES 2
+
+
+/*
+;----------------------------------------------------------------------
+; UNINIT_TI_DAC
+; Prepare DAC for 8514/A compatible mode
+;----------------------------------------------------------------------
+*/
+
+
+void Uninit_ti_dac ()
+{
+
+ passth_8514(OFF); // can only program DAC in 8514 mode
+
+ switch (INP(CONFIG_STATUS_1+1)&0xe)
+ {
+ case TI_DAC:
+
+ /* set EXT_DAC_ADDR field */
+
+ OUTPW (EXT_GE_CONFIG,0x201a);
+
+ /* INPut clock source is CLK0 */
+
+ OUTP (INPUT_CLK_SEL,0);
+
+ /* OUTPut clock is SCLK/1 and VCLK/1 */
+
+ OUTP (OUTPUT_CLK_SEL,0);
+
+ /* set MUX CONTROL TO 8/16 */
+
+ OUTP (MUX_CNTL,0x1d);
+
+ /* set default 8bpp pixel delay and blank adjust */
+
+
+ OUTPW (LOCAL_CNTL,INPW(LOCAL_CNTL) | 8); // TI_DAC_BLANK_ADJUST is always on
+
+ Set_blank_adj(0xc);
+
+ /* set horizontal skew */
+
+ OUTP (HORIZONTAL_OVERSCAN,1);
+ break;
+
+
+ case ATT_DAC:
+
+ OUTPW(EXT_GE_CONFIG,0x101a);
+ OUTP(ATT_MODE_CNTL,0);
+
+
+ default:
+ /* PIXEL_DELAY=0 */
+
+ Set_blank_adj(0);
+
+ /* set horizontal skew */
+
+ OUTPW(HORIZONTAL_OVERSCAN,0);
+ break;
+ }
+
+//
+// reset EXT_DAC_ADDR, put DAC in 6 bit mode, engine in 8 bit mode
+//
+ OUTPW(EXT_GE_CONFIG,0x1a);
+ passth_8514(ON);
+}
+
+
+/*
+;----------------------------------------------------------------------
+; SET_BLANK_ADJ
+; Sets the blank adjust and pixel delay values
+; INPUT: blank adjust and pixel delay
+;----------------------------------------------------------------------
+*/
+
+
+void Set_blank_adj(BYTE adjust)
+{
+BYTE misc;
+
+ misc=INP(R_MISC_CNTL+1) & 0xf0 | adjust;
+
+ OUTP(MISC_CNTL+1,misc);
+
+}
+
+
+
+/************************************************************************
+ * passth_8514()
+ * Turn passthrough off (8514 mode) or on (vga passthrough)
+ * Note that this routine is specific to ATI graphics accelerators.
+ * Generic 8514/A routine should also include setting up CRT parameters
+ * to ensure that the DAC gets a reasonable clock rate.
+ ************************************************************************/
+
+void passth_8514(int status)
+ {
+ OUTP(DISP_CNTL,0x53); /* disable CRT controller */
+
+ if (status == OFF)
+ {
+ OUTPW(ADVFUNC_CNTL,0x7);
+ OUTPW(CLOCK_SEL,INPW(CLOCK_SEL)|1); /* slow down the clock rate */
+ }
+ else
+ {
+ OUTPW(ADVFUNC_CNTL,0x6);
+ OUTPW(CLOCK_SEL,INPW(CLOCK_SEL)&0xfffe); /* speed up the clock rate */
+ }
+ OUTP(DISP_CNTL,0x33); /* enable CRT controller */
+ }
diff --git a/private/ntos/fw/alpha/bldrstub.c b/private/ntos/fw/alpha/bldrstub.c
new file mode 100644
index 000000000..fe742f9ab
--- /dev/null
+++ b/private/ntos/fw/alpha/bldrstub.c
@@ -0,0 +1,287 @@
+/*++
+
+Module Name:
+
+ bldrstub.c
+
+Abstract:
+
+ This module implements stub routines for the boot code.
+
+Author:
+
+ David N. Cutler (davec) 7-Nov-1990
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ 5-April-1993 John DeRosa [DEC]
+
+ This takes the place of bldr\alpha\stubs.c.
+
+--*/
+
+#include "ntos.h"
+#include "fwstring.h"
+
+//
+// Define global data.
+//
+
+ULONG BlDcacheFillSize = 32;
+
+VOID
+KeBugCheck (
+ IN ULONG BugCheckCode
+ )
+
+/*++
+
+Routine Description:
+
+ This function crashes the system in a controlled manner.
+
+ Alpha/Jensen firmware will try to run the Monitor instead of the
+ kernel debugger.
+
+Arguments:
+
+ BugCheckCode - Supplies the reason for the bug check.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+#ifdef ALPHA_FW_KDHOOKS
+ //
+ // Print out the bug check code and break.
+ //
+
+ DbgPrint(ST_BUGCHECK_MSG, BugCheckCode);
+ while(TRUE) {
+ DbgBreakPoint();
+ };
+#else
+
+ //
+ // Print out the bug check code and go to the monitor as an exception.
+ //
+
+ FwPrint(ST_BUGCHECK_MSG, BugCheckCode);
+ FwMonitor(0);
+
+#endif
+
+ return;
+}
+
+LARGE_INTEGER
+KeQueryPerformanceCounter (
+ OUT PLARGE_INTEGER Frequency OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is a stub for the kernel debugger and always returns a
+ value of zero.
+
+Arguments:
+
+ Frequency - Supplies an optional pointer to a variable which receives
+ the performance counter frequency in Hertz.
+
+Return Value:
+
+ A value of zero is returned.
+
+--*/
+
+{
+
+ LARGE_INTEGER Counter;
+
+ //
+ // Return the current system time as the function value.
+ //
+
+ Counter.LowPart = 0;
+ Counter.HighPart = 0;
+
+ return Counter;
+
+}
+
+
+BOOLEAN
+KeFreezeExecution (
+ IN PKTRAP_FRAME TrapFrame,
+ IN PEXCEPTION_RECORD ExceptionRecord
+ )
+
+/*++
+
+Routine Description:
+
+ This function freezes the execution of all other processors in the host
+ configuration and then returns to the caller. It is intended for use by
+ the kernel debugger.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Whether interrupts were previously enabled.
+
+--*/
+
+{
+ return FALSE;
+}
+
+
+VOID
+KeThawExecution (
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This function unfreezes the execution of all other processors in the host
+ configuration and then returns to the caller. It is intended for use by
+ the kernel debugger.
+
+Arguments:
+
+ Irql - Supplies the level that the IRQL is to be lowered to after having
+ unfrozen the execution of all other processors.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ return;
+}
+
+PVOID
+MmDbgReadCheck (
+ IN PVOID VirtualAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This routine returns the phyiscal address for a virtual address
+ which is valid (mapped) for read access.
+
+Arguments:
+
+ VirtualAddress - Supplies the virtual address to check.
+
+Return Value:
+
+ Returns NULL if the address is not valid or readable, otherwise
+ returns the physical address of the corresponding virtual address.
+
+--*/
+
+{
+
+ return VirtualAddress;
+}
+
+PVOID
+MmDbgTranslatePhysicalAddress (
+ IN PHYSICAL_ADDRESS PhysicalAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This routine returns the phyiscal address for a physical address
+ which is valid (mapped).
+
+Arguments:
+
+ PhysicalAddress - Supplies the physical address to check.
+
+Return Value:
+
+ Returns NULL if the address is not valid or readable, otherwise
+ returns the physical address of the corresponding virtual address.
+
+--*/
+
+{
+
+ return (PVOID)PhysicalAddress.LowPart;
+}
+
+PVOID
+MmDbgWriteCheck (
+ IN PVOID VirtualAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This routine returns the phyiscal address for a virtual address
+ which is valid (mapped) for write access.
+
+Arguments:
+
+ VirtualAddress - Supplies the virtual address to check.
+
+Return Value:
+
+ Returns NULL if the address is not valid or readable, otherwise
+ returns the physical address of the corresponding virtual address.
+
+--*/
+
+{
+ return VirtualAddress;
+}
+
+VOID
+RtlAssert(
+ IN PVOID FailedAssertion,
+ IN PVOID FileName,
+ IN ULONG LineNumber,
+ IN PCHAR Message OPTIONAL
+ )
+{
+
+
+#ifdef ALPHA_FW_KDHOOKS
+ DbgPrint( "\n*** Assertion failed\n");
+ while (TRUE) {
+ DbgBreakPoint();
+ }
+#else
+ // Print out the assertion failure and go to the monitor.
+ FwPrint("\r\n*** Assertion failed\r\n");
+ FwMonitor(0);
+
+#endif
+
+}
diff --git a/private/ntos/fw/alpha/conftest.c b/private/ntos/fw/alpha/conftest.c
new file mode 100644
index 000000000..f96b2877a
--- /dev/null
+++ b/private/ntos/fw/alpha/conftest.c
@@ -0,0 +1,1065 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ conftest.c
+
+Abstract:
+
+ This program tests the ARC configuration functions.
+
+Author:
+
+ David M. Robinson (davidro) 4-Sept-1991
+
+Revision History:
+
+ 26-August-1992 John DeRosa [DEC]
+
+ Added Alpha/Jensen modifications.
+
+--*/
+
+#include "fwp.h"
+#include "jnsnvdeo.h"
+#include "oli2msft.h"
+#include "inc.h"
+#include "xxstring.h"
+
+
+VOID
+CtGetString(
+ OUT PCHAR String,
+ IN ULONG StringLength
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads a string from standardin until a
+ carriage return is found or StringLength is reached.
+
+Arguments:
+
+ String - Supplies a pointer to where the string will be stored.
+
+ StringLength - Supplies the Max Length to read.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ CHAR c;
+ ULONG Count;
+ PCHAR Buffer;
+ Buffer = String;
+ while (ArcRead(ARC_CONSOLE_INPUT,&c,1,&Count)==ESUCCESS) {
+ if ((c=='\r') || (c=='\n') || (Buffer-String == StringLength)) {
+ *Buffer='\0';
+ ArcWrite(ARC_CONSOLE_OUTPUT,"\r\n",2,&Count);
+ return;
+ }
+ //
+ // Check for backspace;
+ //
+ if (c=='\b') {
+ if (((ULONG)Buffer > (ULONG)String)) {
+ Buffer--;
+ ArcWrite(ARC_CONSOLE_OUTPUT,"\b \b",3,&Count);
+ }
+ } else {
+ //
+ // Store the character and display it.
+ //
+ *Buffer++ = c;
+ ArcWrite(ARC_CONSOLE_OUTPUT,&c,1,&Count);
+ }
+ }
+}
+
+
+
+VOID
+CtPrintData(
+ PCONFIGURATION_COMPONENT Component
+ )
+
+/*++
+
+--*/
+
+{
+ ARC_STATUS Status;
+ EISA_ADAPTER_DETAILS EisaDetails;
+ PCM_VIDEO_DEVICE_DATA VideoDeviceData;
+ PCM_MONITOR_DEVICE_DATA MonitorDeviceData;
+ PCM_SONIC_DEVICE_DATA SonicDeviceData;
+ PCM_SCSI_DEVICE_DATA ScsiDeviceData;
+ PCM_FLOPPY_DEVICE_DATA FloppyDeviceData;
+ PCM_SERIAL_DEVICE_DATA SerialDeviceData;
+ EXTENDED_SYSTEM_INFORMATION SystemInfo;
+ ULONG LineSize;
+ UCHAR Buffer[sizeof(CM_PARTIAL_RESOURCE_LIST) +
+ (sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * 5) +
+ MAXIMUM_DEVICE_SPECIFIC_DATA];
+ PCM_PARTIAL_RESOURCE_LIST Descriptor = (PCM_PARTIAL_RESOURCE_LIST)&Buffer;
+ ULONG Count;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Partial;
+ ULONG Prid;
+ BOOLEAN OldData;
+ ULONG Version;
+ ULONG Index;
+ BOOLEAN ChildOfEISAAdapter;
+
+ VenPrint("\n\r");
+
+ if (Component == NULL) {
+ VenPrint(" NULL component");
+ return;
+ }
+
+ //
+ // If the parent of this node is the EISA adapter, then the configuration
+ // data, if present, has an ARC-style header with EISA entries, which
+ // we will not attempt to decode.
+ //
+
+ if ((ArcGetParent(Component) != NULL) &&
+ (ArcGetParent(Component)->Type == EisaAdapter)) {
+ ChildOfEISAAdapter = TRUE;
+ } else {
+ ChildOfEISAAdapter = FALSE;
+ }
+
+ if (Component->IdentifierLength != 0) {
+ VenPrint(" Identifier = ");
+ VenPrint(Component->Identifier);
+ }
+ VenPrint("\r\n");
+
+ OldData = FALSE;
+ switch (Component->Class) {
+
+ case SystemClass:
+ VenPrint(" Class = System\r\n");
+ VenPrint(" Type = ");
+ if (Component->Type == ArcSystem) {
+ VenPrint("Arc");
+ } else {
+ VenPrint("Unknown");
+ }
+ VenPrint("\r\n");
+ break;
+
+ case ProcessorClass:
+ VenPrint(" Class = Processor\r\n");
+ VenPrint(" Type = ");
+
+ switch (Component->Type) {
+ case CentralProcessor:
+ VenPrint("CPU");
+ break;
+
+ case FloatingPointProcessor:
+ VenPrint("FPU");
+ break;
+
+ default:
+ VenPrint("Unknown");
+ break;
+ }
+
+ VenPrint("\r\n");
+ VenPrint1(" Number = %d\r\n", Component->Key);
+
+ VenReturnExtendedSystemInformation(&SystemInfo);
+ VenPrint1(" Processor Id= %d.\r\n", SystemInfo.ProcessorId);
+ VenPrint1(" Revision = %d.\r\n", SystemInfo.ProcessorRevision);
+ VenPrint1(" Firmware Rev= %s\r\n", &SystemInfo.FirmwareVersion[0]);
+
+ break;
+
+ case CacheClass:
+ VenPrint(" Class = Cache\r\n");
+ VenPrint(" Type = ");
+
+ switch (Component->Type) {
+ case PrimaryIcache:
+ VenPrint("Primary Instruction");
+ break;
+
+ case PrimaryDcache:
+ VenPrint("Primary Data");
+ break;
+
+ case SecondaryIcache:
+ VenPrint("Secondary Instruction");
+ break;
+
+ case SecondaryDcache:
+ VenPrint("Secondary Data");
+ break;
+
+ case SecondaryCache:
+ VenPrint("Secondary");
+ break;
+
+ default:
+ VenPrint("Unknown");
+ break;
+
+ }
+
+ LineSize = 1 << ((Component->Key & 0xFF0000) >> 16);
+ VenPrint("\r\n");
+ VenPrint1(" Block = %d\r\n", ((Component->Key & 0xFF000000) >> 24) * LineSize);
+ VenPrint1(" Line = %d\r\n", LineSize);
+ VenPrint1(" Size = %d\r\n", (1 << (Component->Key & 0xFFFF) << PAGE_SHIFT));
+ break;
+
+ case MemoryClass:
+ VenPrint(" Class = Memory\r\n");
+ VenPrint(" Type = ");
+
+ switch (Component->Type) {
+ case SystemMemory:
+ VenPrint("SystemMemory\r\n");
+ break;
+
+ default:
+ VenPrint("Unknown\r\n");
+ break;
+ }
+ break;
+
+ case AdapterClass:
+ VenPrint(" Class = Adapter\r\n");
+ VenPrint(" Type = ");
+
+ switch (Component->Type) {
+ case EisaAdapter:
+ VenPrint("EISA");
+ OldData = TRUE;
+ break;
+
+ case TcAdapter:
+ VenPrint("Turbochannel");
+ break;
+
+ case ScsiAdapter:
+ VenPrint("SCSI");
+ break;
+
+ case DtiAdapter:
+ VenPrint("Desktop Interface");
+ break;
+
+ case MultiFunctionAdapter:
+ VenPrint("Multifunction");
+ break;
+
+ default:
+ VenPrint("Unknown");
+ break;
+
+ }
+ VenPrint("\r\n");
+ break;
+
+ case ControllerClass:
+ VenPrint(" Class = Controller\r\n");
+ VenPrint(" Type = ");
+
+ switch (Component->Type) {
+
+ case DiskController:
+ VenPrint("Disk");
+ break;
+
+ case TapeController:
+ VenPrint("Tape");
+ break;
+
+ case CdromController:
+ VenPrint("CDROM");
+ break;
+
+ case WormController:
+ VenPrint("WORM");
+ break;
+
+ case SerialController:
+ VenPrint("Serial");
+ break;
+
+ case NetworkController:
+ VenPrint("Network");
+ break;
+
+ case DisplayController:
+ VenPrint("Display");
+ break;
+
+ case ParallelController:
+ VenPrint("Parallel");
+ break;
+
+ case PointerController:
+ VenPrint("Pointer");
+ break;
+
+ case KeyboardController:
+ VenPrint("Keyboard");
+ break;
+
+ case AudioController:
+ VenPrint("Audio");
+ break;
+
+ case OtherController:
+ VenPrint("Other");
+ break;
+
+ default:
+ VenPrint("Unknown");
+ break;
+
+ }
+ VenPrint("\r\n");
+ break;
+
+ case PeripheralClass:
+ VenPrint(" Class = Peripheral\r\n");
+ VenPrint(" Type = ");
+
+ switch (Component->Type) {
+
+ case DiskPeripheral:
+ VenPrint("Disk");
+ break;
+
+ case FloppyDiskPeripheral:
+ VenPrint("Floppy disk");
+ break;
+
+ case TapePeripheral:
+ VenPrint("Tape");
+ break;
+
+ case ModemPeripheral:
+ VenPrint("Modem");
+ break;
+
+ case PrinterPeripheral:
+ VenPrint("Printer");
+ break;
+
+ case KeyboardPeripheral:
+ VenPrint("Keyboard");
+ break;
+
+ case PointerPeripheral:
+ VenPrint("Pointer");
+ break;
+
+ case MonitorPeripheral:
+ VenPrint("Monitor");
+ break;
+
+ case TerminalPeripheral:
+ VenPrint("Terminal");
+ break;
+
+ case OtherPeripheral:
+ VenPrint("Other");
+ break;
+
+ default:
+ VenPrint("Unknown");
+ break;
+
+ }
+ VenPrint("\r\n");
+ break;
+
+
+ default:
+ VenPrint(" Unknown class,");
+ break;
+ }
+
+ VenPrint1(" Key = %08lx\r\n", Component->Key);
+ VenPrint1(" Affinity = %08lx\r\n", Component->AffinityMask);
+ VenPrint(" Flags:\r\n");
+
+ if (Component->Flags.Failed) {
+ VenPrint(" Failed\r\n");
+ }
+
+ if (Component->Flags.ReadOnly) {
+ VenPrint(" ReadOnly\r\n");
+ }
+
+ if (Component->Flags.Removable) {
+ VenPrint(" Removable\r\n");
+ }
+
+ if (Component->Flags.ConsoleIn) {
+ VenPrint(" ConsoleIn\r\n");
+ }
+
+ if (Component->Flags.ConsoleOut) {
+ VenPrint(" ConsoleOut\r\n");
+ }
+
+ if (Component->Flags.Input) {
+ VenPrint(" Input\r\n");
+ }
+
+ if (Component->Flags.Output) {
+ VenPrint(" Output\r\n");
+ }
+
+ VenPrint("\r\n");
+
+ if (!ChildOfEISAAdapter &&
+ !OldData &&
+ (Component->ConfigurationDataLength != 0) &&
+ (Component->ConfigurationDataLength < sizeof(Buffer))) {
+
+ //
+ // This is not a child of the EISA adapter, and it is also not the
+ // EISA adapter itself. Try to get and print out the configuration
+ // data.
+ //
+
+ Status = ArcGetConfigurationData( Descriptor, Component );
+
+ if ((Status != ESUCCESS) || (Descriptor->Count > 10)) {
+
+ VenPrint(" Error reading configuration data");
+
+ } else {
+
+ VenPrint2(" Version %d.%d\r\n", Descriptor->Version, Descriptor->Revision);
+ Version = Descriptor->Version * 100 + Descriptor->Revision;
+
+ for (Count = 0 ; Count < Descriptor->Count ; Count++ ) {
+
+ Partial = &Descriptor->PartialDescriptors[Count];
+
+ switch (Partial->Type) {
+
+ case CmResourceTypePort:
+ VenPrint2(" Port Config -- %08lx - %08lx\r\n",
+ Partial->u.Port.Start.LowPart,
+ Partial->u.Port.Start.LowPart +
+ Partial->u.Port.Length - 1);
+ break;
+ case CmResourceTypeInterrupt:
+ VenPrint(" Interrupt Config -- ");
+ if (Partial->Flags & CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE) {
+ VenPrint(" Level triggered,");
+ } else {
+ VenPrint(" Edge triggered,");
+ }
+ VenPrint(" Irql = ");
+ switch (Partial->u.Interrupt.Level) {
+ case DEVICE_LEVEL:
+ VenPrint("DEVICE_LEVEL");
+ break;
+ case PASSIVE_LEVEL:
+ VenPrint("PASSIVE_LEVEL");
+ break;
+ case APC_LEVEL:
+ VenPrint("APC_LEVEL");
+ break;
+ case DISPATCH_LEVEL:
+ VenPrint("DISPATCH_LEVEL");
+ break;
+ case IPI_LEVEL:
+ VenPrint("IPI_LEVEL");
+ break;
+ case HIGH_LEVEL:
+ VenPrint("HIGH_LEVEL");
+ break;
+ default:
+ VenPrint("Unknown level");
+ }
+ VenPrint1(", Vector = %08lx\r\n", Partial->u.Interrupt.Vector);
+ break;
+ case CmResourceTypeMemory:
+ VenPrint2(" Memory Config -- %08lx - %08lx\r\n",
+ Partial->u.Memory.Start.LowPart,
+ Partial->u.Memory.Start.LowPart +
+ Partial->u.Memory.Length - 1);
+ break;
+ case CmResourceTypeDma:
+ VenPrint1(" DMA Config -- Channel = %d\r\n",
+ Partial->u.Dma.Channel);
+ break;
+ case CmResourceTypeDeviceSpecific:
+ switch (Component->Class) {
+
+ case AdapterClass:
+ switch (Component->Type) {
+ case ScsiAdapter:
+ ScsiDeviceData = (PCM_SCSI_DEVICE_DATA)&Descriptor->PartialDescriptors[Count+1];
+ VenPrint1(" Scsi Host Identifier = %d\r\n",
+ ScsiDeviceData->HostIdentifier);
+ break;
+ default:
+ break;
+ }
+
+ case ControllerClass:
+ switch (Component->Type) {
+ case DisplayController:
+ VideoDeviceData = (PCM_VIDEO_DEVICE_DATA)&Descriptor->PartialDescriptors[Count+1];
+ VenPrint1(" Video Clock = %d\r\n",
+ VideoDeviceData->VideoClock);
+ break;
+ case NetworkController:
+ SonicDeviceData = (PCM_SONIC_DEVICE_DATA)&Descriptor->PartialDescriptors[Count+1];
+ VenPrint1(" Sonic Data Configuration Register = %04x\r\n",
+ SonicDeviceData->DataConfigurationRegister);
+ if (Version >= 101) {
+ VenPrint(" Sonic Ethernet Address = ");
+ for (Index = 0; Index < 6 ; Index++) {
+ VenPrint1("%02lx", SonicDeviceData->EthernetAddress[Index]);
+ }
+ VenPrint("\r\n");
+ VenPrint(" Sonic Ethernet Checksum = ");
+ for (Index = 6; Index < 8 ; Index++) {
+ VenPrint1("%02lx", SonicDeviceData->EthernetAddress[Index]);
+ }
+ VenPrint("\r\n");
+
+ }
+ break;
+
+ case SerialController:
+ SerialDeviceData = (PCM_SERIAL_DEVICE_DATA)&Descriptor->PartialDescriptors[Count+1];
+ VenPrint1(" Serial Baud Clock = %d\r\n",
+ SerialDeviceData->BaudClock);
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case PeripheralClass:
+
+ switch (Component->Type) {
+
+ case FloppyDiskPeripheral:
+ FloppyDeviceData = (PCM_FLOPPY_DEVICE_DATA)&Descriptor->PartialDescriptors[Count+1];
+ VenPrint(" Floppy data:\n\r");
+ VenPrint1(" Size = %s\n\r", FloppyDeviceData->Size);
+ VenPrint1(" MaxDensity = %d Kb\n\r", FloppyDeviceData->MaxDensity);
+ break;
+
+ case MonitorPeripheral:
+ MonitorDeviceData = (PCM_MONITOR_DEVICE_DATA)&Descriptor->PartialDescriptors[Count+1];
+ VenPrint(" Monitor data:\n\r");
+ VenPrint1(" HorizontalResolution = %d\n\r", MonitorDeviceData->HorizontalResolution);
+ VenPrint1(" HorizontalDisplayTime = %d\n\r", MonitorDeviceData->HorizontalDisplayTime);
+ VenPrint1(" HorizontalBackPorch = %d\n\r", MonitorDeviceData->HorizontalBackPorch);
+ VenPrint1(" HorizontalFrontPorch = %d\n\r", MonitorDeviceData->HorizontalFrontPorch);
+ VenPrint1(" HorizontalSync = %d\n\r", MonitorDeviceData->HorizontalSync);
+ VenPrint1(" VerticalResolution = %d\n\r", MonitorDeviceData->VerticalResolution);
+ VenPrint1(" VerticalBackPorch = %d\n\r", MonitorDeviceData->VerticalBackPorch);
+ VenPrint1(" VerticalFrontPorch = %d\n\r", MonitorDeviceData->VerticalFrontPorch);
+ VenPrint1(" VerticalSync = %d\n\r", MonitorDeviceData->VerticalSync);
+ VenPrint1(" HorizontalScreenSize = %d\n\r", MonitorDeviceData->HorizontalScreenSize);
+ VenPrint1(" VerticalScreenSize = %d\n\r", MonitorDeviceData->VerticalScreenSize);
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ VenPrint(" Unknown data\r\n");
+ break;
+ }
+ }
+ }
+
+ } else if (OldData &&
+ (Component->ConfigurationDataLength != 0) &&
+ (Component->ConfigurationDataLength < sizeof(Buffer))) {
+
+ //
+ // This is old-style configuration data, i.e. the eisa adapter
+ // itself.
+ //
+
+ Status = ArcGetConfigurationData( &EisaDetails, Component);
+ if (Status != ESUCCESS) {
+ VenPrint(" Error reading Eisa bus data");
+ } else {
+ VenPrint(" Eisa Details:\n\r");
+ VenPrint1(" Number of slots = %d\n\r", EisaDetails.NumberOfSlots);
+ VenPrint1(" Io start address = %08lx\n\r", EisaDetails.IoStart);
+ VenPrint1(" Io size = %lx\n\r", EisaDetails.IoSize);
+ }
+ }
+
+ return;
+}
+VOID
+main(
+ int argc,
+ char *argv[],
+ char *envp[]
+ )
+{
+ BOOLEAN EisaMachine;
+ ULONG Index;
+ UCHAR Character;
+ ULONG Count;
+ LONG DefaultChoice = 0;
+ ARC_STATUS Status;
+ CHAR PathName[80];
+ PCONFIGURATION_COMPONENT Component;
+ PCONFIGURATION_COMPONENT NewComponent;
+ PSYSTEM_ID SystemId;
+ BOOLEAN Update;
+ PMEMORY_DESCRIPTOR MemoryDescriptor;
+ PCHAR Choices[] = {
+ "Walk through the configuration tree",
+ "Enter a pathname and display the configuration data",
+ "Display memory configuration",
+ "Test Unicode",
+ "Other ARC Tests",
+ "Exit"
+ };
+#define NUMBER_OF_CHOICES (sizeof(Choices) / sizeof(ULONG))
+ ULONG Fid;
+ ULONG CrLf;
+ ULONG Space;
+ ULONG i, j;
+ BOOLEAN Unicode;
+ PARC_DISPLAY_STATUS DisplayStatus;
+ ULONG x, y;
+
+ while (TRUE) {
+
+ VenSetScreenAttributes( TRUE, FALSE, FALSE);
+ VenPrint1("%c2J", ASCII_CSI);
+ VenSetPosition( 0, 0);
+
+#if defined(JENSEN)
+ VenPrint(" Jensen Configuration Test Program Version 1.09\r\n");
+#elif defined(MORGAN)
+ VenPrint(" Morgan Configuration Test Program Version 1.09\r\n");
+#endif
+
+ VenPrint(" Copyright (c) 1993 Microsoft Corporation, Digital Equipment Corporation\r\n\n");
+
+ for (Index = 0; Index < NUMBER_OF_CHOICES ; Index++ ) {
+ VenSetPosition( Index + 4, 5);
+ if (Index == DefaultChoice) {
+ VenSetScreenAttributes( TRUE, FALSE, TRUE);
+ VenPrint(Choices[Index]);
+ VenSetScreenAttributes( TRUE, FALSE, FALSE);
+ } else {
+ VenPrint(Choices[Index]);
+ }
+ }
+
+ VenSetPosition(NUMBER_OF_CHOICES + 5, 0);
+ SystemId = ArcGetSystemId();
+ VenPrint1(" System = %s\r\n", &SystemId->VendorId[0]);
+ VenPrint1(" Serial = %s\r\n", &SystemId->ProductId[0]);
+
+ Character = 0;
+ do {
+ if (ArcGetReadStatus(ARC_CONSOLE_INPUT) == ESUCCESS) {
+ ArcRead(ARC_CONSOLE_INPUT, &Character, 1, &Count);
+ switch (Character) {
+
+ case ASCII_ESC:
+
+ VenStallExecution(10000);
+ if (ArcGetReadStatus(ARC_CONSOLE_INPUT) == ESUCCESS) {
+ ArcRead(ARC_CONSOLE_INPUT, &Character, 1, &Count);
+ if (Character != '[') {
+ return;
+ }
+ } else {
+ return;
+ }
+
+ // We purposely fall through to ASCII_CSI.
+
+ case ASCII_CSI:
+ ArcRead(ARC_CONSOLE_INPUT, &Character, 1, &Count);
+ VenSetPosition( DefaultChoice + 4, 5);
+ VenPrint(Choices[DefaultChoice]);
+ switch (Character) {
+ case 'A':
+ case 'D':
+ DefaultChoice--;
+ if (DefaultChoice < 0) {
+ DefaultChoice = NUMBER_OF_CHOICES-1;
+ }
+ break;
+ case 'B':
+ case 'C':
+ DefaultChoice++;
+ if (DefaultChoice == NUMBER_OF_CHOICES) {
+ DefaultChoice = 0;
+ }
+ break;
+ case 'H':
+ DefaultChoice = 0;
+ break;
+ default:
+ break;
+ }
+ VenSetPosition( DefaultChoice + 4, 5);
+ VenSetScreenAttributes( TRUE, FALSE, TRUE);
+ VenPrint(Choices[DefaultChoice]);
+ VenSetScreenAttributes( TRUE, FALSE, FALSE);
+ continue;
+
+ default:
+ break;
+ }
+ }
+
+ } while ((Character != '\n') && (Character != '\r'));
+
+ switch (DefaultChoice) {
+
+ case 0:
+
+ Component = ArcGetChild(NULL);
+ NewComponent = Component;
+ Character = 0;
+ do {
+
+ VenSetPosition( 4, 5);
+ VenPrint("\x9BJ");
+ VenPrint("Use arrow keys to walk the tree, ESC to return");
+ VenPrint("\n\r\n");
+
+ CtPrintData(Component);
+ Update = FALSE;
+ do {
+ if (ArcGetReadStatus(ARC_CONSOLE_INPUT) == ESUCCESS) {
+ ArcRead(ARC_CONSOLE_INPUT, &Character, 1, &Count);
+ switch (Character) {
+
+ case ASCII_ESC:
+
+ VenStallExecution(10000);
+
+ if (ArcGetReadStatus(ARC_CONSOLE_INPUT) == ESUCCESS) {
+ ArcRead(ARC_CONSOLE_INPUT, &Character, 1, &Count);
+ if (Character != '[') {
+ Character = ASCII_ESC;
+ break;
+ }
+ } else {
+ Character = ASCII_ESC;
+ break;
+ }
+
+ // We purposely fall through to ASCII_CSI.
+
+
+ case ASCII_CSI:
+ ArcRead(ARC_CONSOLE_INPUT, &Character, 1, &Count);
+ switch (Character) {
+ case 'A':
+ NewComponent = ArcGetParent(Component);
+ Update = TRUE;
+ break;
+
+ case 'B':
+ NewComponent = ArcGetChild(Component);
+ Update = TRUE;
+ break;
+
+ case 'C':
+ NewComponent = ArcGetPeer(Component);
+ Update = TRUE;
+ break;
+
+ case 'D':
+ NewComponent = ArcGetParent(Component);
+ NewComponent = ArcGetChild(NewComponent);
+ while ((NewComponent != NULL) &&
+ (ArcGetPeer(NewComponent) != Component)) {
+ NewComponent = ArcGetPeer(NewComponent);
+ }
+ Update = TRUE;
+ break;
+
+ default:
+ break;
+
+ }
+
+ if (NewComponent != NULL) {
+ Component = NewComponent;
+ }
+
+ default:
+ break;
+ }
+ }
+ } while (!Update && (Character != ASCII_ESC));
+ } while (Character != ASCII_ESC);
+ break;
+
+ case 1:
+
+ VenSetPosition( 4, 5);
+ VenPrint("\x9BJ");
+ VenPrint("Enter component pathname: ");
+ CtGetString( PathName, sizeof(PathName));
+ VenPrint("\n\r");
+
+ Component = ArcGetComponent(PathName);
+
+ CtPrintData(Component);
+
+ VenPrint(" Press any key to continue...");
+ ArcRead(ARC_CONSOLE_INPUT, &Character, 1, &Count);
+ continue;
+
+ case 2:
+
+ MemoryDescriptor = ArcGetMemoryDescriptor(NULL);
+ while (MemoryDescriptor != NULL) {
+
+ VenSetPosition( 4, 5);
+ VenPrint("\x9BJ");
+
+ VenPrint("Memory type = ");
+ switch (MemoryDescriptor->MemoryType) {
+ case MemoryExceptionBlock:
+ VenPrint("ExceptionBlock");
+ break;
+ case MemorySystemBlock:
+ VenPrint("SystemBlock");
+ break;
+ case MemoryFree:
+ VenPrint("Free");
+ break;
+ case MemoryBad:
+ VenPrint("Bad");
+ break;
+ case MemoryLoadedProgram:
+ VenPrint("LoadedProgram");
+ break;
+ case MemoryFirmwareTemporary:
+ VenPrint("FirmwareTemporary");
+ break;
+ case MemoryFirmwarePermanent:
+ VenPrint("FirmwarePermanent");
+ break;
+ case MemoryFreeContiguous:
+ VenPrint("FreeContiguous");
+ break;
+ case MemorySpecialMemory:
+ VenPrint("SpecialMemory");
+ break;
+ default:
+ VenPrint("Unknown");
+ break;
+ }
+
+ VenSetPosition( 5, 5);
+ VenPrint1("Base Page = %08lx", MemoryDescriptor->BasePage);
+ VenSetPosition( 6, 5);
+ VenPrint1("Page Count = 0x%x", MemoryDescriptor->PageCount);
+ VenSetPosition( 7, 5);
+
+
+ VenPrint(" Press any key to continue, ESC to return");
+ ArcRead(ARC_CONSOLE_INPUT, &Character, 1, &Count);
+ if (Character == ASCII_ESC) {
+ break;
+ }
+
+ MemoryDescriptor = ArcGetMemoryDescriptor(MemoryDescriptor);
+ }
+ break;
+
+ case 3:
+
+ VenPrint("\r\n\n");
+ CrLf = (ASCII_CR << 16) + ASCII_LF;
+ Space = ' ';
+
+ ArcClose(ARC_CONSOLE_OUTPUT);
+
+ //
+ // Try opening all the possible legal output devices.
+ //
+
+ EisaMachine = TRUE;
+ if (ArcOpen(EISA_UNICODE_CONSOLE_OUT,ArcOpenWriteOnly,&Fid) != ESUCCESS) {
+ EisaMachine = FALSE;
+ ArcOpen(MULTI_UNICODE_CONSOLE_OUT,ArcOpenWriteOnly,&Fid);
+ }
+
+ for (j = 0; j < 16 ; j++ ) {
+ for (i = 0 ; i < 9 ; i++ ) {
+ Index = 0x2500 + (i << 4) + j;
+ ArcWrite(ARC_CONSOLE_OUTPUT, &Space, 2, &Count);
+ ArcWrite(ARC_CONSOLE_OUTPUT, &Index, 2, &Count);
+ }
+ ArcWrite(ARC_CONSOLE_OUTPUT, &CrLf, 4, &Count);
+ }
+
+ ArcClose(ARC_CONSOLE_OUTPUT);
+
+ if (EisaMachine) {
+ ArcOpen(EISA_NORMAL_CONSOLE_OUT,ArcOpenWriteOnly,&Fid);
+ } else {
+ ArcOpen(MULTI_NORMAL_CONSOLE_OUT,ArcOpenWriteOnly,&Fid);
+ }
+
+ VenPrint("\r\nPress any key to continue");
+ ArcRead(ARC_CONSOLE_INPUT, &Character, 1, &Count);
+
+
+ ArcClose(ARC_CONSOLE_INPUT);
+
+ ArcOpen(MULTI_UNICODE_KEYBOARD_IN,ArcOpenReadOnly,&Fid);
+ if (EisaMachine) {
+ ArcOpen(EISA_UNICODE_CONSOLE_OUT,ArcOpenWriteOnly,&Fid);
+ } else {
+ ArcOpen(MULTI_UNICODE_CONSOLE_OUT,ArcOpenWriteOnly,&Fid);
+ }
+
+ do {
+ VenPrint("\r\nPress any key, ESC to stop: ");
+ ArcRead(ARC_CONSOLE_INPUT, &Index, 2, &Count);
+ ArcWrite(Fid, &Index, 2, &Count);
+ } while ( Index != ASCII_ESC );
+
+ VenPrint(" \r\n Searching for valid Unicode ranges...");
+
+ Unicode = FALSE;
+ for (Index = 0; Index < 0xffff ; Index++ ) {
+ if (ArcTestUnicodeCharacter(Fid, (WCHAR)Index) == ESUCCESS) {
+ if (!Unicode) {
+ VenPrint1("\r\n Start = %04lx, ", Index);
+ Unicode = TRUE;
+ }
+ } else {
+ if (Unicode) {
+ VenPrint1("End = %04lx, ", Index);
+ Unicode = FALSE;
+ }
+ }
+ }
+
+ ArcClose(Fid);
+ ArcClose(ARC_CONSOLE_INPUT);
+ ArcOpen(MULTI_NORMAL_KEYBOARD_IN,ArcOpenReadOnly,&Fid);
+
+ VenPrint("\r\nPress any key to continue");
+ ArcRead(ARC_CONSOLE_INPUT, &Character, 1, &Count);
+
+ break;
+
+ case 4:
+
+ DisplayStatus = ArcGetDisplayStatus(ARC_CONSOLE_OUTPUT);
+
+ x = (DisplayStatus->CursorMaxXPosition / 2) - 24;
+ y = (DisplayStatus->CursorMaxYPosition / 2) - 7;
+
+ VenSetPosition(y++,x);
+
+ VenPrint("ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»");
+
+ for (Index = 0; Index < 10 ; Index++ ) {
+ VenSetPosition(y++,x);
+ VenPrint("º º");
+ }
+ VenSetPosition(y++,x);
+ VenPrint("ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ");
+
+ x = (DisplayStatus->CursorMaxXPosition / 2) - 23;
+ y = (DisplayStatus->CursorMaxYPosition / 2) - 6;
+
+ VenSetPosition(y++,x);
+ VenSetScreenColor(ArcColorCyan,ArcColorBlack);
+
+ VenPrint("ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»");
+
+ for (Index = 0; Index < 6 ; Index++ ) {
+ VenSetPosition(y++,x);
+ VenPrint("º º");
+ }
+ VenSetPosition(y++,x);
+ VenPrint("ÇÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĶ");
+ VenSetPosition(y++,x);
+ VenPrint("º º");
+ VenSetPosition(y++,x);
+ VenPrint("ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ");
+
+ x = (DisplayStatus->CursorMaxXPosition / 2) - 22;
+ y = (DisplayStatus->CursorMaxYPosition / 2) - 5;
+ VenSetPosition(y++,x);
+
+ DisplayStatus = ArcGetDisplayStatus(ARC_CONSOLE_OUTPUT);
+
+ VenPrint1("X Cursor = %d", DisplayStatus->CursorXPosition);
+ VenSetPosition(y++,x);
+ VenPrint1("Y Cursor = %d", DisplayStatus->CursorYPosition);
+ VenSetPosition(y++,x);
+ VenPrint1("Max X Cursor = %d", DisplayStatus->CursorMaxXPosition);
+ VenSetPosition(y++,x);
+ VenPrint1("Max Y Cursor = %d", DisplayStatus->CursorMaxYPosition);
+
+
+ VenSetPosition(y++,x);
+ VenPrint("Press any key to continue...");
+ ArcRead(ARC_CONSOLE_INPUT, &Character, 1, &Count);
+
+ for (Index = 0; Index < argc ; Index++ ) {
+ VenPrint1("\r\n Argument #%d = ", Index);
+ VenPrint(argv[Index]);
+ }
+
+ if (argc == 0) {
+ VenPrint("\r\n No arguments");
+ }
+
+ VenPrint("\r\n Press any key to continue...");
+ ArcRead(ARC_CONSOLE_INPUT, &Character, 1, &Count);
+
+ break;
+
+ case 5:
+ return;
+
+ default:
+ continue;
+ }
+ }
+}
diff --git a/private/ntos/fw/alpha/conftest.rsp b/private/ntos/fw/alpha/conftest.rsp
new file mode 100644
index 000000000..88a06e30d
--- /dev/null
+++ b/private/ntos/fw/alpha/conftest.rsp
@@ -0,0 +1,11 @@
+-machine:alpha
+-fixed
+-rom
+-base:0x80080000
+-align:0x100
+-debug:none
+-debugtype:coff
+-entry:main
+obj\alpha\conftest.obj
+obj\alpha\xxstring.obj
+\nt\public\sdk\lib\alpha\libcnt.lib
diff --git a/private/ntos/fw/alpha/debug.h b/private/ntos/fw/alpha/debug.h
new file mode 100644
index 000000000..d72c62146
--- /dev/null
+++ b/private/ntos/fw/alpha/debug.h
@@ -0,0 +1,7 @@
+
+#if OMF_DEBUG==TRUE
+ #define PRINTDBG(x) FwPrint(x); \
+ FwStallExecution(50*1000);
+#else
+ #define PRINTDBG(x) //
+#endif
diff --git a/private/ntos/fw/alpha/eisafunc.c b/private/ntos/fw/alpha/eisafunc.c
new file mode 100644
index 000000000..119a041c1
--- /dev/null
+++ b/private/ntos/fw/alpha/eisafunc.c
@@ -0,0 +1,693 @@
+// ----------------------------------------------------------------------------
+// Copyright (c) 1992 Olivetti
+// Copyright (c) 1993 Digital Equipment Corporation
+//
+// File: eisafunc.c
+//
+// Description: Eisa code support functions.
+//
+// Revision:
+//
+// 3-December-1992 John DeRosa [DEC]
+//
+// Alpha_AXP/Jensen compiles disable the same code as Jazz
+// compiles. An additional disables was added. The result is that
+// this file generates no code for Jensen.
+//
+// ----------------------------------------------------------------------------
+//
+
+#include "fwp.h"
+#include "oli2msft.h"
+#include "arceisa.h"
+#include "inc.h"
+#include "string.h"
+#include "debug.h"
+
+extern EISA_BUS_INFO EisaBusInfo[];
+extern BL_FILE_TABLE BlFileTable [BL_FILE_TABLE_SIZE];
+
+// Function prototypes.
+
+
+VOID
+EisaFlushCache
+ (
+ IN PVOID Address,
+ IN ULONG Length
+ );
+
+VOID
+EisaInvalidateCache
+ (
+ IN PVOID Address,
+ IN ULONG Length
+ );
+
+ARC_STATUS
+EisaDoLockedOperation
+ (
+ IN ULONG BusNumber,
+ IN EISA_LOCK_OPERATION Operation,
+ IN PVOID Semaphore,
+ IN SEMAPHORE_SIZE SemaphoreSize,
+ IN PVOID OperationArgument,
+ OUT PVOID OperationResult
+ );
+
+ARC_STATUS
+EisaCheckLockPassingParameters
+ (
+ IN ULONG BusNumber,
+ IN EISA_LOCK_OPERATION Operation,
+ IN PVOID Semaphore,
+ IN SEMAPHORE_SIZE SemaphoreSize,
+ IN PVOID OperationArgument,
+ OUT PVOID OperationResult
+ );
+
+VOID
+EisaFlushWriteBuffers
+ (
+ VOID
+ );
+
+ARC_STATUS
+EisaGenerateTone
+ (
+ IN ULONG Frequency,
+ IN ULONG Duration
+ );
+
+BOOLEAN_ULONG
+EisaYield
+ (
+ VOID
+ );
+
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaFlushCache:
+//
+// DESCRIPTION: This function flushes the instruction and data caches
+// starting at the address specified in "Address" for
+// number of bytes specified in "Length".
+//
+// ARGUMENTS: Address - Starting virtual address of a range of virtual
+// addresses that are to be flushed from the instruction
+// and data caches. If Address is 0 the entire instruction
+// and data caches are flushed.
+//
+// Length - The length of range of virtual addresses that
+// are to be flushed from the instruction and data caches.
+//
+// RETURN: none
+//
+// ASSUMPTIONS:
+//
+// CALLS: GetICacheSize, GetDCacheSize, FlushInvalidateDCacheIndex
+//
+// GLOBALS: none.
+//
+// NOTES:
+// ----------------------------------------------------------------------------
+//
+
+// NOTE: Not used on JAZZ or Jensen.
+#if 0
+
+VOID
+EisaFlushCache
+ (
+ IN PVOID Address,
+ IN ULONG Length
+ )
+{
+ ULONG CacheSize;
+ ULONG CacheLineSize;
+
+ if ( !Length ) // flush entire cache ?
+ { // yes, get cache sizes and flush
+
+ GetDCacheSize( (ULONG)&CacheSize, (ULONG)&CacheLineSize );
+ FlushInvalidateDCacheIndex( (PVOID)KSEG0_BASE, CacheSize );
+
+ return; // return to caller
+ }
+
+//
+// User specified a specific address to flush. So take the users starting
+// virtual address and size and flush data cache.
+//
+
+ Address = (PVOID)((ULONG)Address & 0x1FFFFFFF | KSEG0_BASE);
+ FlushInvalidateDCacheIndex( Address, Length );
+
+ return; // return
+}
+
+#endif // 0
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaInvalidateCache:
+//
+// DESCRIPTION: This functions sets the invalid bit in the cache line for
+// the specified range of addresses.
+//
+// ARGUMENTS: Address - Starting virtual address of a range of virtual
+// addresses that are to be invalidated in the instruction
+// and data caches. If Address is 0 the entire instruction
+// and data caches are invalidated.
+//
+// Length - The length of range of virtual addresses that
+// are to be invalidated in the instruction and data caches.
+//
+// RETURN: none
+//
+// ASSUMPTIONS: none
+//
+// CALLS: GetICacheSize, GetDCacheSize, InvalidateICacheIndex,
+// FlushInvalidateDCacheIndex
+//
+// GLOBALS: none
+//
+// NOTES:
+// ----------------------------------------------------------------------------
+//
+
+// NOTE: Not used on JAZZ or Jensen.
+#if 0
+
+VOID
+EisaInvalidateCache
+ (
+ IN PVOID Address,
+ IN ULONG Length
+ )
+{
+ ULONG CacheSize;
+ ULONG CacheLineSize;
+
+ if ( !Length ) // invalidate entire cache ?
+ { // yes, get cache sizes and invalidate
+
+ GetDCacheSize( (ULONG)&CacheSize, (ULONG)&CacheLineSize );
+ FlushInvalidateDCacheIndex( (PVOID)KSEG0_BASE, CacheSize );
+
+ GetICacheSize( (ULONG)&CacheSize, (ULONG)&CacheLineSize );
+ InvalidateICacheIndex( (PVOID)KSEG0_BASE, CacheSize );
+
+ return; // return to caller
+ }
+
+//
+// User specified a specific address to invalidate. So take the users
+// starting virtual address and size and invalidate both instruction and
+// data caches.
+//
+
+ Address = (PVOID)((ULONG)Address & 0x1FFFFFFF | KSEG0_BASE);
+ FlushInvalidateDCacheIndex( Address, Length );
+ InvalidateICacheIndex( Address, Length );
+
+ return; // return to caller
+}
+
+#endif // 0
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaDoEISALockedOperation:
+//
+// DESCRIPTION: A CPU or a bus master can assert LOCK* to guarantee
+// exclusive memory access during the time LOCK* is
+// asserted. Assertion of LOCK* allows bit test and set
+// operations (as used for semaphores) to be executed
+// as a unit (atomically), with the bus lock preventing
+// multiple devices from simultaneously modifying the
+// semaphore bit. The MIPS family of microprocessors
+// does not assert LOCK* during the execution of any
+// function. As such, the system firmware provides an
+// abstracted programmatic interface through which option
+// module firmware (OMF) can assert and negate LOCK*.
+//
+// EISA option module firmware's LOCK* requests are
+// performed by the EISA LOCK function. If there are
+// multiple EISA buses in the system, the buses may share
+// the LOCK hardware among the different EISA buses.
+//
+// ARGUMENTS: BusNumber The bus that contains the device that
+// is sharing semaphore. This number is
+// the Key of the buses' component
+// structure.
+//
+// Opeation The type of locked operation to be
+// performed.
+//
+// Semaphore A pointer to the varialbe in EISA or
+// system memory.
+//
+// SemaphoreSize The size of the semaphore.
+//
+// OperationArgument The value to change the Semaphore to.
+//
+// OperationResult A pointer to a memory location that
+// will receive the value of Semaphore
+// before Operation.
+//
+// RETURN: ESUCCESS all done
+// EINVAL passing parameters error
+//
+// ASSUMPTIONS: none
+//
+// CALLS: EisaCheckLockPassingParameters
+//
+// GLOBALS: none
+//
+// NOTES:
+// ----------------------------------------------------------------------------
+//
+
+// NOTE: Not used on JAZZ or Jensen.
+#if 0
+
+ARC_STATUS
+EisaDoLockedOperation
+ (
+ IN ULONG BusNumber,
+ IN EISA_LOCK_OPERATION Operation,
+ IN PVOID Semaphore,
+ IN SEMAPHORE_SIZE SemaphoreSize,
+ IN PVOID OperationArgument,
+ OUT PVOID OperationResult
+ )
+{
+ ARC_STATUS Status;
+
+ //
+ // validate the passing parameters to avoind exceptions.
+ //
+
+ if ( Status = EisaCheckLockPassingParameters( BusNumber, Operation,
+ Semaphore, SemaphoreSize, OperationArgument, OperationResult ))
+ {
+ return Status;
+ }
+
+ //
+ // assert lock on the BUS.
+ //
+
+ WRITE_PORT_UCHAR( EISA_LOCK_VIRTUAL_BASE,
+ READ_PORT_UCHAR( EISA_LOCK_VIRTUAL_BASE ) | 0x01 );
+
+ //
+ // Now check to see what type of operation the caller is asking us
+ // to perform.
+ //
+
+ if (Operation == Exchange)
+ {
+ //
+ // User wants to exchange the current semaphore value with the
+ // one passed. So, lets get the semaphore size and do the
+ // exchange.
+ //
+
+ switch(SemaphoreSize)
+ {
+ case ByteSemaphore:
+ *(PUCHAR)OperationResult = *(PUCHAR)Semaphore;
+ *(PUCHAR)Semaphore = *(PUCHAR)OperationArgument;
+ break;
+
+ case HalfWordSemaphore:
+ *(PUSHORT)OperationResult = *(PUSHORT)Semaphore;
+ *(PUSHORT)Semaphore = *(PUSHORT)OperationArgument;
+ break;
+
+ case WordSemaphore:
+ *(PULONG)OperationResult = *(PULONG)Semaphore;
+ *(PULONG)Semaphore = *(PULONG)OperationArgument;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ //
+ // The operation on the semaphore is now complete. Now we need to
+ // negate the LOCK* signal.
+ //
+
+ WRITE_PORT_UCHAR( EISA_LOCK_VIRTUAL_BASE,
+ READ_PORT_UCHAR( EISA_LOCK_VIRTUAL_BASE ) & 0xFE );
+
+ return ESUCCESS;
+}
+
+#endif // 0
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaCheckLockPassingParameters:
+//
+// DESCRIPTION: The functions checks the lock function passing
+// parameters. This is neccessary to avoin exceptions.
+//
+// ARGUMENTS: BusNumber The bus that contains the device that
+// is sharing semaphore. This number is
+// the Key of the buses' component
+// structure.
+//
+// Opeation The type of locked operation to be
+// performed.
+//
+// Semaphore A pointer to the varialbe in EISA or
+// system memory.
+//
+// SemaphoreSize The size of the semaphore.
+//
+// OperationArgument The value to change the Semaphore to.
+//
+// OperationResult A pointer to a memory location that
+// will receive the value of Semaphore
+// before Operation.
+//
+// RETURN: ESUCCESS parameters are correct.
+// EINVAL at least one parameter was not correct.
+//
+// ASSUMPTIONS: none
+//
+// CALLS: EisaCheckBusNumber
+//
+// GLOBALS: none
+//
+// NOTES: none
+// ----------------------------------------------------------------------------
+//
+
+// NOTE: Not used on JAZZ or Jensen.
+#if 0
+
+ARC_STATUS
+EisaCheckLockPassingParameters
+ (
+ IN ULONG BusNumber,
+ IN EISA_LOCK_OPERATION Operation,
+ IN PVOID Semaphore,
+ IN SEMAPHORE_SIZE SemaphoreSize,
+ IN PVOID OperationArgument,
+ OUT PVOID OperationResult
+ )
+{
+ ARC_STATUS Status = EINVAL;
+ ULONG Size = 1 << SemaphoreSize; // semaphore size (# bytes)
+
+ //
+ // check the bus number
+ //
+
+ if ( EisaCheckBusNumber( BusNumber ) != ESUCCESS );
+
+ //
+ // check lock operation
+ //
+
+ else if ( Operation >= LockMaxOperation );
+
+ //
+ // check semaphore size
+ //
+
+ else if ( SemaphoreSize >= MaxSemaphore );
+
+ //
+ // make sure that there is physical memory at the specified locations
+ //
+
+ else if ( EisaCheckVirtualAddress( BusNumber, Semaphore, Size ));
+ else if ( EisaCheckVirtualAddress( BusNumber, OperationArgument, Size ));
+ else if ( EisaCheckVirtualAddress( BusNumber, OperationResult, Size ));
+
+ //
+ // check pointers boundaries
+ //
+
+ else if ( ((ULONG)Semaphore | (ULONG)OperationArgument |
+ (ULONG)OperationResult) & ((1 << SemaphoreSize)-1) );
+
+ //
+ // if we got here, the parameters are correct
+ //
+
+ else
+ {
+ Status = ESUCCESS;
+ }
+
+ return Status;
+}
+
+#endif // 0
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaFlushWriteBuffers:
+//
+// DESCRIPTION: This function flushes any external write buffers.
+//
+// ARGUMENTS: none.
+//
+// RETURN: none
+//
+// ASSUMPTIONS: none
+//
+// CALLS: FlushWriteBuffers
+//
+// GLOBALS: none
+//
+// NOTES:
+// ----------------------------------------------------------------------------
+//
+
+// NOTE: Not used on JAZZ or Jensen.
+#if 0
+
+VOID
+EisaFlushWriteBuffers
+ (
+ VOID
+ )
+{
+ FlushWriteBuffers(); // flush external write buffers.
+ return; // return to caller.
+}
+
+#endif // 0
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaGenerateTone:
+//
+// DESCRIPTION: This function generate tones of a specified
+// frequency and duration an the system speaker.
+//
+// ARGUMENTS: Frequency the frequency of the tone in hertz
+// Duration The duration of the tone in msec
+//
+// RETURN: ESUCCESS Operation completed successfully
+// ENODEV System can not generate tones
+//
+// ASSUMPTIONS: none
+//
+// CALLS: none
+//
+// GLOBALS: none
+//
+// NOTES: The routine uses the timer1-counter2 and the system
+// control port B of the 1st EISA bus to generate the
+// specified tone.
+// ----------------------------------------------------------------------------
+//
+
+// NOTE: Not used on Jensen.
+#if 0
+
+ARC_STATUS
+EisaGenerateTone
+ (
+ IN ULONG Frequency,
+ IN ULONG Duration
+ )
+{
+ //
+ // define local variables
+ //
+
+ PUCHAR EisaIoStart, Ctrl, Data, Port61; // general I/O address
+
+ //
+ // exit if duration is null
+ //
+
+ if ( !Duration )
+ {
+ return ESUCCESS;
+ }
+
+ //
+ // initialize local variables
+ //
+
+ EisaIoStart = EisaBusInfo[ 0 ].IoBusInfo->VirAddr;
+ Ctrl = EisaIoStart + EISA_TIMER1_CTRL;
+ Data = EisaIoStart + EISA_TIMER1_COUNTER2;
+ Port61 = EisaIoStart + EISA_SYS_CTRL_PORTB;
+
+ //
+ // make sure that the speaker is disabled
+ //
+
+ EisaOutUchar( Port61, ( EisaInUchar( Port61 ) &
+ ~( EISA_SPEAKER_GATE | EISA_SPEAKER_TIMER )) & 0x0F );
+
+ //
+ // if frequency value is valid, program timer1-counter2 and enable speaker
+ //
+
+ if (Frequency>=EISA_SPEAKER_MIN_FREQ && Frequency<=EISA_SPEAKER_MAX_FREQ)
+ {
+ //
+ // initialize timer1 counter2 in 16-bit , mode 3
+ //
+
+// NOTE: CriticalSection not supported in JAZZ.
+// EisaBeginCriticalSection();
+ EisaOutUchar( Ctrl, 0xB6 );
+ EisaOutUchar( Data, (UCHAR)(EISA_SPEAKER_CLOCK/Frequency));
+ EisaOutUchar( Data, (UCHAR)(EISA_SPEAKER_CLOCK/Frequency >> 8));
+// NOTE: CriticalSection not supported in JAZZ.
+// EisaEndCriticalSection();
+
+ //
+ // enable speaker gate and speaker output
+ //
+
+ EisaOutUchar( Port61, ( EisaInUchar( Port61 ) |
+ EISA_SPEAKER_GATE | EISA_SPEAKER_TIMER ) & 0x0F );
+ }
+
+ //
+ // ... wait
+ //
+
+ while ( Duration-- )
+ {
+ ArcEisaStallProcessor( 1000 ); // 1 msec
+ }
+
+ //
+ // disable speaker before returning
+ //
+
+ EisaOutUchar( Port61, ( EisaInUchar( Port61 ) &
+ ~( EISA_SPEAKER_GATE | EISA_SPEAKER_TIMER )) & 0x0F );
+
+ //
+ // all done
+ //
+
+ return ESUCCESS;
+}
+
+
+#endif // 0
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaYield:
+//
+// DESCRIPTION: System utilities and option module firmware
+// must surrender the processor so that the system
+// module firmware can check for pending input.
+// To surrender the prcessor, call this function.
+//
+// ARGUMENTS: none
+//
+// RETURN: TRUE Indicates that the BREAK key was
+// pressed. Yield continues to return
+// TREUE until the BREAK key is read
+// from the console input device.
+// FALSE Inidicates that the BREAK key has
+// not been pressed.
+// ASSUMPTIONS: none
+//
+// CALLS: none
+//
+// GLOBALS: none
+//
+// NOTES: none
+// ----------------------------------------------------------------------------
+//
+
+// NOTE: Not used on JAZZ or Jensen.
+#if 0
+
+BOOLEAN_ULONG
+EisaYield
+ (
+ VOID
+ )
+{
+ //
+ // call all device strategy routines with FC_POLL command
+ //
+
+ EisaOmfPoll();
+
+ //
+ // read any char available from the console in into the console in buffer
+ //
+
+ if ( !BlFileTable[ 0 ].Flags.Open )
+ {
+ //
+ // the console in device is not available, return no Ctrl-C.
+ //
+
+ return FALSE;
+ }
+
+ //
+ // read any available data from the console in device
+ //
+
+ ConsoleInFill();
+
+ //
+ // and scan buffer checking contrl-C
+ //
+
+ return ConsoleInCtrlC();
+}
+
+#endif // 0
diff --git a/private/ntos/fw/alpha/eisaini.c b/private/ntos/fw/alpha/eisaini.c
new file mode 100644
index 000000000..8a22a089d
--- /dev/null
+++ b/private/ntos/fw/alpha/eisaini.c
@@ -0,0 +1,3420 @@
+// ----------------------------------------------------------------------------
+// Copyright (c) 1992 Olivetti
+// Copyright (c) 1992, 1993 Digital Equipment Corporation
+//
+// File: eisaini.c
+//
+// Description: EISA initialization routines.
+//
+// This is also built in for ISA machines, as a simple
+// way of initializing the System Parameter Block vectors.
+// Another way of doing this would be to change the code
+// in jxboot.c and fwio.c
+//
+// Revision:
+//
+// 3-December-1992 John DeRosa [DEC]
+//
+// Added Alpha_AXP/Jensen modifications. Most of these were for
+// page size effects.
+//
+// ----------------------------------------------------------------------------
+//
+
+#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
+ );
+
+ARC_STATUS
+FwRememberEisabuffer(
+ IN ULONG Addr,
+ IN ULONG Size
+ );
+
+// ----------------------------------------------------------------------------
+// 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
+// ----------------------------------------------------------------------------
+
+
+#ifdef EISA_PLATFORM
+
+//
+// Build this in only if doing a build for a real EISA machine, and not ISA.
+//
+
+// 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
+
+#endif
+
+
+
+// ----------------------------------------------------------------------------
+// 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();
+
+#ifdef ISA_PLATFORM
+
+ //
+ // ISA machines need to call this function just to set up
+ // the adapter vectors. They should return now.
+ //
+
+ return;
+
+#else
+
+// 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;
+ }
+
+ //
+ // 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();
+
+ //
+ // all done
+ //
+
+ return;
+
+#endif // ISA_PLATFORM
+
+}
+
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaGeneralIni:
+//
+// DESCRIPTION: This function performs general initialization
+// for the EISA buses.
+//
+// For ISA machines, this routine is used as an easy
+// way to initialize the SPB vectors properly.
+//
+// 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;
+
+#ifdef EISA_PLATFORM
+ SYSTEM_BLOCK->Adapter0Type = EisaAdapter;
+#else
+ SYSTEM_BLOCK->Adapter0Type = MultiFunctionAdapter;
+#endif
+
+ //
+ // Initialize the Adapter Length. For ISA machines, this wastes a small
+ // amount of memory after the vendor vector.
+ //
+
+ SYSTEM_BLOCK->Adapter0Length = (ULONG)MaximumEisaRoutine * sizeof(ULONG);
+
+ SYSTEM_BLOCK->Adapter0Vector = (PVOID)((PUCHAR)SYSTEM_BLOCK->VendorVector +
+ SYSTEM_BLOCK->VendorVectorLength);
+
+#ifdef EISA_PLATFORM
+
+ //
+ // 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] = FwpReservedRoutine;
+
+ (PEISA_END_CRITICAL_SECTION_RTN)SYSTEM_BLOCK->Adapter0Vector
+// [EndCriticalSectionRoutine] = EisaEndCriticalSection;
+ [EndCriticalSectionRoutine] = FwpReservedRoutine;
+
+ (PEISA_GENERATE_TONE_RTN)SYSTEM_BLOCK->Adapter0Vector
+// [GenerateToneRoutine] = EisaGenerateTone;
+ [GenerateToneRoutine] = FwpReservedRoutine;
+
+ (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;
+
+#endif // EISA_PLATFORM
+
+ //
+ // all done
+ //
+
+ return;
+}
+
+
+
+
+
+
+
+
+
+#ifdef EISA_PLATFORM
+
+// ----------------------------------------------------------------------------
+// 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 8k 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;
+ pIoBusInfo->PagNumb = 64 * 1024 / PAGE_SIZE;
+
+ ((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 8k 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;
+}
+
+
+#endif // EISA_PLATFORM
+
+
+
+
+
+
+#ifdef EISA_PLATFORM
+// ----------------------------------------------------------------------------
+// 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;
+}
+
+
+
+
+#endif // EISA_PLATFORM
+
+
+
+
+
+
+#ifdef EISA_PLATFORM
+
+// ----------------------------------------------------------------------------
+// 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 was not 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;
+}
+
+#endif // EISA_PLATFORM
+
+
+
+
+
+
+#ifdef EISA_PLATFORM
+
+// ----------------------------------------------------------------------------
+// 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 ));
+}
+
+
+#endif // EISA_PLATFORM
+
+
+
+
+
+
+#ifdef EISA_PLATFORM
+
+// ----------------------------------------------------------------------------
+// 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 ));
+}
+
+#endif // EISA_PLATFORM
+
+
+
+
+
+
+#ifdef EISA_PLATFORM
+
+// ----------------------------------------------------------------------------
+// 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 are any memory entries
+ //
+
+ //
+ // The Alpha AXP/Jensen machine needs to mark EISA memory buffers
+ // as "Bad" in the memory descriptors so that NT will not try to
+ // use them for anything.
+ //
+ // So, EISA memory functions are not supported on Jazz, and they
+ // are supported only for memory marking on Jensen.
+ //
+
+ 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;
+}
+
+#endif // EISA_PLATFORM
+
+
+
+
+
+
+#ifdef EISA_PLATFORM
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaSlotCfgMem:
+//
+// DESCRIPTION: The original version of this function configured
+// the eisa memory registers based on info from NVRAM.
+//
+// This version will mark the EISA buffer addresses as
+// "Bad" in the memory descriptors, to fix the Jensen
+// EISA/memory aliasing problem.
+//
+// ARGUMENTS: BusNumber EISA bus number.
+// SlotNumber EISA slot number.
+// EisaFuncInfo Function info pointer.
+//
+// RETURN: TRUE All done
+// FALSE Error
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+// ----------------------------------------------------------------------------
+//
+
+#if 0
+
+//
+// Original version
+//
+
+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;
+}
+
+#else
+
+//
+// Alpha/AXP Jensen version.
+//
+
+BOOLEAN
+EisaSlotCfgMem
+ (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PUCHAR EisaFuncInfo
+ )
+{
+ ARC_STATUS Status;
+ PUCHAR MemBlock; // start of DMA data buffer
+ USHORT Index = 0; // index within the memory block
+ ULONG Addr; // address in 256 units
+ ULONG Size; // size in 1k units
+
+ PRINTDBG("EisaSlotCfgMem\n\r"); // DEBUG SUPPORT
+
+ //
+ // initialize variables
+ //
+
+ MemBlock = &EisaFuncInfo[ CFG_MEM_BLK_OFS ];
+
+ //
+ // one loop per each memory entry
+ //
+
+ do {
+ //
+ // memory block start and length
+ //
+
+ Addr = Fw3UcharToUlongLSB( &MemBlock[Index + 2] ) * 0x100;
+ Size = Fw2UcharToUlongLSB( &MemBlock[Index + 5] ) * 0x400;
+
+ if ((Status = FwRememberEisaBuffer((Addr >> PAGE_SHIFT),
+ (Size >> PAGE_SHIFT)) != ESUCCESS)) {
+ FwPrint(EISA_CANT_MARK_BUFFER_MSG, Status);
+ EisaSlotErrorLog( BusNumber, SlotNumber, BufferMarkError);
+ FwStallExecution(2000000);
+ return(FALSE);
+ }
+
+ } while ((MemBlock[Index]&CFG_MORE_ENTRY) && ((Index+=7)<CFG_MEM_BLK_LEN));
+
+ //
+ // check final index
+ //
+
+ if (Index >= CFG_MEM_BLK_LEN) {
+ FwPrint(EISA_BAD_INDEX_MSG, Index, CFG_MEM_BLK_LEN);
+ FwStallExecution(2000000);
+ return(FALSE);
+ } else {
+ return(TRUE);
+ }
+}
+
+#endif
+
+#endif // EISA_PLATFORM
+
+
+
+
+
+
+#ifdef EISA_PLATFORM
+
+// ----------------------------------------------------------------------------
+// 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 shareable
+ //
+
+ 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;
+}
+
+#endif // EISA_PLATFORM
+
+
+
+
+
+
+#ifdef EISA_PLATFORM
+
+// ----------------------------------------------------------------------------
+// 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;
+}
+
+#endif // EISA_PLATFORM
+
+
+
+
+
+
+#ifdef EISA_PLATFORM
+
+// ----------------------------------------------------------------------------
+// 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_PORT_UCHAR(EisaIoStart+IoPort) & ByteMask;
+ EISA_IO_DELAY;
+ }
+
+ if ((IoPort & 0x0FFF) == EXPANSION_BOARD_CTRL_BITS)
+ {
+ *EnabAdapter=FALSE;
+ }
+ WRITE_PORT_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_PORT_USHORT((PUSHORT)(EisaIoStart + IoPort)) &
+ ShortMask;
+ EISA_IO_DELAY;
+ }
+
+ WRITE_PORT_USHORT((PUSHORT)(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_PORT_ULONG((PULONG)(EisaIoStart + IoPort)) &
+ WordMask;
+ EISA_IO_DELAY;
+ }
+
+ WRITE_PORT_ULONG((PULONG)(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;
+}
+
+
+#endif // EISA_PLATFORM
+
+
+
+
+
+
+#ifdef EISA_PLATFORM
+
+// ----------------------------------------------------------------------------
+// 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
+
+ EISAErrorFwPrint2(EISA_ERROR_SLOT_MSG, SlotNumber, EisaCfgMessages[ErrorCode] );
+ FwMoveCursorToColumn( 37 );
+ EISAErrorFwPrint(EISA_ERROR1_MSG);
+
+ // all done
+
+ return;
+}
+
+
+
+#endif // EISA_PLATFORM
+
+
+
+
+
+
+#ifdef EISA_PLATFORM
+
+// ----------------------------------------------------------------------------
+// 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;
+}
+
+
+#endif // EISA_PLATFORM
+
+
+
+
+
+
+#ifdef EISA_PLATFORM
+
+// ----------------------------------------------------------------------------
+// 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
+
+ EISAErrorFwPrint2( "\r\n %s %s ", Str, EisaCfgMessages[ErrorCode] );
+ if ( strlen(Str) + strlen(EisaCfgMessages[ErrorCode]) + 2 < 36 )
+ {
+ FwMoveCursorToColumn( 37 );
+ }
+
+ EISAErrorFwPrint(EISA_ERROR1_MSG);
+
+ return;
+}
+
+
+#endif // EISA_PLATFORM
+
+
+
+
+
+
+#ifdef EISA_PLATFORM
+
+// ----------------------------------------------------------------------------
+// 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;
+}
+
+
+#endif // EISA_PLATFORM
+
+
+
+
+
+
+#ifdef EISA_PLATFORM
+
+// ----------------------------------------------------------------------------
+// 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
+ {
+ EISAErrorFwPrint1( "%s", EisaCheckpointInfo[ Chk ].Msg );
+ }
+ }
+
+ 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.
+}
+
+
+#endif // EISA_PLATFORM
+
+
+
+
+
+
+#ifdef EISA_PLATFORM
+
+// ----------------------------------------------------------------------------
+// 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;
+}
+
+#endif // EISA_PLATFORM
+
+
+
+
+
+
+#ifdef EISA_PLATFORM
+
+// ----------------------------------------------------------------------------
+// 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_PORT_UCHAR(RefreshPort) & EISA_REFRESH;
+
+ Retry &&
+ RefreshStatus == (READ_PORT_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;
+}
+
+
+#endif // EISA_PLATFORM
+
+
+
+
+
+
+#ifdef EISA_PLATFORM
+
+// ----------------------------------------------------------------------------
+// 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
+
+
+#endif // EISA_PLATFORM
+
+
+
+
+
+
+#ifdef EISA_PLATFORM
+
+// ----------------------------------------------------------------------------
+// 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
+
+#endif // EISA_PLATFORM
+
+
+
+
+
+
+#ifdef EISA_PLATFORM
+
+// ----------------------------------------------------------------------------
+// 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;
+}
+
+
+#endif // EISA_PLATFORM
+
+
+
+
+
+
+#ifdef EISA_PLATFORM
+
+// ----------------------------------------------------------------------------
+// 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;
+}
+
+
+
+#endif // EISA_PLATFORM
+
+
+
+
+
+
+#ifdef EISA_PLATFORM
+
+// ----------------------------------------------------------------------------
+// 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];
+}
+
+
+#endif // EISA_PLATFORM
+
+
+
+
+
+
+#ifdef EISA_PLATFORM
+
+// ----------------------------------------------------------------------------
+// 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
+
+
+
+#endif // EISA_PLATFORM
+
+
+
+
+
+
+#ifdef EISA_PLATFORM
+
+// ----------------------------------------------------------------------------
+// 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;
+}
+
+
+
+
+#endif // EISA_PLATFORM
diff --git a/private/ntos/fw/alpha/eisamisc.c b/private/ntos/fw/alpha/eisamisc.c
new file mode 100644
index 000000000..b35d3e110
--- /dev/null
+++ b/private/ntos/fw/alpha/eisamisc.c
@@ -0,0 +1,213 @@
+// ----------------------------------------------------------------------------
+// Copyright (c) 1992 Olivetti
+//
+// File: eisamisc.c
+//
+// Description: Miscellaneous EISA routines.
+// ----------------------------------------------------------------------------
+//
+
+#include "fwp.h"
+#include "oli2msft.h"
+#include "arceisa.h"
+#include "inc.h"
+#include "string.h"
+#include "debug.h"
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: Fw2UcharToUlongLSB:
+//
+// DESCRIPTION: This function converts 2 uchars to an ulong.
+//
+// ARGUMENTS: String String holding 2 uchars:
+//
+// String[0] LSB
+// String[1] MSB
+//
+// RETURN: ULONG corrisponding ulong value:
+//
+// 0 +
+// 0 +
+// String[1] << 8 +
+// String[0]
+//
+//
+//
+// ASSUMPTIONS: none
+//
+// CALLS: none
+//
+// GLOBALS: none
+//
+// NOTES: none
+// ----------------------------------------------------------------------------
+//
+
+ULONG
+Fw2UcharToUlongLSB
+ (
+ IN PUCHAR String
+ )
+{
+ PRINTDBG("Fw2UcharToUlongLSB\n\r"); // DEBUG SUPPORT
+
+ return ((ULONG)(String[1]) << BITSXBYTE) + (ULONG)(String[0]);
+}
+
+
+
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: Fw3UcharToUlongLSB:
+//
+// DESCRIPTION: This function converts 3 uchars to an ulong.
+//
+// ARGUMENTS: String String holding 3 uchars:
+//
+// String[0] LSB
+// String[1] 2nd
+// String[2] MSB
+//
+// RETURN: ULONG corrisponding ulong value:
+//
+// 0 +
+// String[2] << 16 +
+// String[1] << 8 +
+// String[0]
+//
+//
+//
+// ASSUMPTIONS: none
+//
+// CALLS: none
+//
+// GLOBALS: none
+//
+// NOTES: none
+// ----------------------------------------------------------------------------
+//
+
+ULONG
+Fw3UcharToUlongLSB
+ (
+ IN PUCHAR String
+ )
+{
+ PRINTDBG("Fw2UcharToUlongLSB\n\r"); // DEBUG SUPPORT
+
+ return ((ULONG)(String[2]) << 2*BITSXBYTE) +
+ ((ULONG)(String[1]) << BITSXBYTE) +
+ (ULONG)(String[0]);
+}
+
+
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: Fw4UcharToUlongLSB:
+//
+// DESCRIPTION: This function converts 4 uchars to an ulong.
+//
+// ARGUMENTS: String String holding 4 uchars:
+//
+// String[0] LSB
+// String[1] 2nd
+// String[2] 3rd
+// String[3] MSB
+//
+// RETURN: ULONG corrisponding ulong value:
+//
+// String[3] << 24 +
+// String[2] << 16 +
+// String[1] << 8 +
+// String[0]
+//
+//
+//
+// ASSUMPTIONS: none
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+// ----------------------------------------------------------------------------
+//
+
+ULONG
+Fw4UcharToUlongLSB
+ (
+ IN PUCHAR String
+ )
+{
+ PRINTDBG("Fw4UcharToUlongLSB\n\r"); // DEBUG SUPPORT
+
+ return ((ULONG)(String[3]) << 3*BITSXBYTE) +
+ ((ULONG)(String[2]) << 2*BITSXBYTE) +
+ ((ULONG)(String[1]) << BITSXBYTE) +
+ (ULONG)(String[0]);
+}
+
+
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: Fw4UcharToUlongMSB:
+//
+// DESCRIPTION: This function converts 4 uchars to an ulong.
+//
+// ARGUMENTS: String String holding 4 uchars:
+//
+// String[0] MSB
+// String[1] 3rd
+// String[2] 2nd
+// String[3] LSB
+//
+// RETURN: ULONG corrisponding ulong value:
+//
+// String[0] << 24 +
+// String[1] << 16 +
+// String[2] << 8 +
+// String[3]
+//
+//
+//
+// ASSUMPTIONS: none
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+// ----------------------------------------------------------------------------
+//
+
+ULONG
+Fw4UcharToUlongMSB
+ (
+ IN PUCHAR String
+ )
+{
+ PRINTDBG("Fw4UcharToUlongMSB\n\r"); // DEBUG SUPPORT
+
+ return ((ULONG)(String[0]) << 3*BITSXBYTE) +
+ ((ULONG)(String[1]) << 2*BITSXBYTE) +
+ ((ULONG)(String[2]) << BITSXBYTE) +
+ (ULONG)(String[3]);
+}
+
+
+
+
diff --git a/private/ntos/fw/alpha/eisapod.c b/private/ntos/fw/alpha/eisapod.c
new file mode 100644
index 000000000..34ec93d1b
--- /dev/null
+++ b/private/ntos/fw/alpha/eisapod.c
@@ -0,0 +1,3694 @@
+// ----------------------------------------------------------------------------
+// Copyright (c) 1992 Olivetti
+// Copyright (c) 1993 Digital Equipment Corporation
+//
+// File: eisapod.c
+//
+// Description: EISA power-on diagnostics.
+//
+// Revision:
+//
+// 3-December-1992 John DeRosa [DEC]
+//
+// Added Alpha_AXP/Jensen modifications.
+// ----------------------------------------------------------------------------
+//
+
+#include "fwp.h"
+#include "oli2msft.h"
+#include "arceisa.h"
+#include "inc.h"
+#include "string.h"
+#include "debug.h"
+#include "eisastr.h"
+
+extern EISA_BUS_INFO EisaBusInfo[];
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// Define Function Prototypes
+// ----------------------------------------------------------------------------
+
+BOOLEAN
+EisaBusPod
+ (
+ IN ULONG BusNumber
+ );
+
+BOOLEAN
+EisaIntPod
+ (
+ IN PUCHAR EisaIoStart,
+ IN PEISA_INT_INFO pIntInfo
+ );
+
+VOID
+EisaPicIni
+ (
+ IN PUCHAR EisaIoStart,
+ IN PEISA_INT_INFO pIntInfo
+ );
+
+BOOLEAN
+EisaPicRegTest
+ (
+ IN PUCHAR EisaIoStart,
+ IN PEISA_INT_INFO pIntInfo
+ );
+
+BOOLEAN
+EisaClearPendingInts
+ (
+ IN PUCHAR EisaIoStart,
+ IN PEISA_INT_INFO pIntInfo
+ );
+
+BOOLEAN
+EisaDmaPod
+ (
+ IN PUCHAR EisaIoStart,
+ IN PEISA_DMA_INFO pDmaInfo
+ );
+
+BOOLEAN
+EisaDmaMaskTest
+ (
+ IN PUCHAR EisaIoStart,
+ IN PEISA_DMA_INFO pDmaInfo
+ );
+
+BOOLEAN
+EisaDmaPageTest
+ (
+ IN PUCHAR EisaIoStart,
+ IN PEISA_DMA_INFO pDmaInfo
+ );
+
+BOOLEAN
+EisaDmaAddressTest
+ (
+ IN PUCHAR EisaIoStart,
+ IN PEISA_DMA_INFO pDmaInfo
+ );
+
+BOOLEAN
+EisaDmaCountTest
+ (
+ IN PUCHAR EisaIoStart,
+ IN PEISA_DMA_INFO pDmaInfo
+ );
+
+BOOLEAN
+EisaDmaStopTest
+ (
+ IN PUCHAR EisaIoStart,
+ IN PEISA_DMA_INFO pDmaInfo
+ );
+
+VOID
+EisaDmaIni
+ (
+ IN PUCHAR EisaIoStart,
+ IN PEISA_DMA_INFO pDmaInfo
+ );
+
+BOOLEAN
+EisaOtherPod
+ (
+ IN PUCHAR EisaIoStart,
+ IN PEISA_PORT_INFO pPortInfo
+ );
+
+BOOLEAN
+EisaNmiTest
+ (
+ IN PUCHAR EisaIoStart,
+ IN PEISA_PORT_INFO pPortInfo
+ );
+
+BOOLEAN
+EisaNmiHandlerTest
+ (
+ IN ULONG Couse
+ );
+
+BOOLEAN
+EisaNmiHandler
+ (
+ IN ULONG Couse
+ );
+
+VOID
+EisaParityError
+ (
+ IN PUCHAR EisaIoStart
+ );
+
+VOID
+EisaIoChkError
+ (
+ IN PUCHAR EisaIoStart,
+ IN ULONG Slots
+ );
+
+VOID
+EisaBusTimeoutError
+ (
+ IN PUCHAR EisaIoStart,
+ IN ULONG Slots
+ );
+
+VOID
+EisaSlaveTimeoutError
+ (
+ IN PUCHAR EisaIoStart,
+ IN ULONG Slots
+ );
+
+BOOLEAN
+EisaRefreshTest
+ (
+ IN PUCHAR EisaIoStart,
+ IN PEISA_PORT_INFO pPortInfo
+ );
+
+BOOLEAN
+EisaPort61Test
+ (
+ IN PUCHAR EisaIoStart,
+ IN PEISA_PORT_INFO pPortInfo
+ );
+
+BOOLEAN
+EisaTimer1Test
+ (
+ IN PUCHAR EisaIoStart,
+ IN PEISA_PORT_INFO pPortInfo
+ );
+
+BOOLEAN
+EisaTimer2Test
+ (
+ IN PUCHAR EisaIoStart,
+ IN PEISA_PORT_INFO pPortInfo
+ );
+
+
+
+// ----------------------------------------------------------------------------
+// Define EISA Function Prototypes
+// ----------------------------------------------------------------------------
+
+VOID
+EisaClearPendingInt
+ (
+ IN PUCHAR EisaIoStart,
+ IN PEISA_INT_INFO pIntInfo,
+ IN USHORT Irq
+ );
+
+UCHAR
+EisaAckInt
+ (
+ IN PEISA_INT_INFO pIntInfo
+ );
+
+VOID
+EisaSendSpecificEoi
+ (
+ IN PUCHAR EisaIoStart,
+ IN USHORT Irq
+ );
+
+VOID
+EisaDisableParityIoCheck
+ (
+ IN PUCHAR EisaIoStart
+ );
+
+VOID
+EisaEnableParityIoCheck
+ (
+ IN PUCHAR EisaIoStart
+ );
+
+VOID
+EisaDisableInt
+ (
+ VOID
+ );
+
+VOID
+EisaDisableNmi
+ (
+ IN PUCHAR EisaIoStart
+ );
+
+VOID
+EisaEnableNmi
+ (
+ IN PUCHAR EisaIoStart
+ );
+
+BOOLEAN
+EisaCheckReg
+ (
+ IN PUCHAR Port,
+ IN UCHAR DataMask
+ );
+
+BOOLEAN
+EisaCheckDeepReg
+ (
+ IN PUCHAR Port
+ );
+
+UCHAR
+EisaReadRtc
+ (
+ IN PUCHAR EisaIoStart,
+ IN ULONG RtcIndex
+ );
+
+VOID
+EisaOutUchar
+ (
+ IN PUCHAR Addr,
+ IN UCHAR Value
+ );
+
+UCHAR
+EisaInUchar
+ (
+ IN PUCHAR Addr
+ );
+
+
+
+// ----------------------------------------------------------------------------
+// Define Global Variables
+// ----------------------------------------------------------------------------
+
+EISA_DMA_REGS_TEST EisaDmaRegsTest[ EISA_DMAS ] =
+ {
+ { DMA_ADDR_0, DMA_PAGE_0, DMA_HPAGE_0,
+ DMA_COUNT_0, DMA_HCOUNT_0, DMA_STOP_0 },
+ { DMA_ADDR_1, DMA_PAGE_1, DMA_HPAGE_1,
+ DMA_COUNT_1, DMA_HCOUNT_1, DMA_STOP_1 },
+ { DMA_ADDR_2, DMA_PAGE_2, DMA_HPAGE_2,
+ DMA_COUNT_2, DMA_HCOUNT_2, DMA_STOP_2 },
+ { DMA_ADDR_3, DMA_PAGE_3, DMA_HPAGE_3,
+ DMA_COUNT_3, DMA_HCOUNT_3, DMA_STOP_3 },
+ { DMA_ADDR_4, DMA_PAGE_RFR, 0,
+ DMA_COUNT_4, 0, 0 },
+ { DMA_ADDR_5, DMA_PAGE_5, DMA_HPAGE_5,
+ DMA_COUNT_5, DMA_HCOUNT_5, DMA_STOP_5 },
+ { DMA_ADDR_6, DMA_PAGE_6, DMA_HPAGE_6,
+ DMA_COUNT_6, DMA_HCOUNT_6, DMA_STOP_6 },
+ { DMA_ADDR_7, DMA_PAGE_7, DMA_HPAGE_7,
+ DMA_COUNT_7, DMA_HCOUNT_7, DMA_STOP_7 }
+ };
+
+EISA_DMA_CTRL_TEST EisaDmaCtrlTest[ 2 ] =
+ {
+ {DMA_MASK_CLR03, DMA_MASKS03, DMA_1MASK03, DMA_MASK_STAT03, DMA_CHAIN03},
+ {DMA_MASK_CLR47, DMA_MASKS47, DMA_1MASK47, DMA_MASK_STAT47, DMA_CHAIN47}
+ };
+
+
+BOOLEAN EisaNmiFlag; // for NMI testing
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaBusPod:
+//
+// DESCRIPTION: This function initializes the hardware of the
+// specified EISA bus.
+//
+// ARGUMENTS: BusNumber EISA bus number
+//
+// RETURN: TRUE All done
+// FALSE Error
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+//
+// ----------------------------------------------------------------------------
+//
+
+BOOLEAN
+EisaBusPod
+ (
+ IN ULONG BusNumber
+ )
+{
+ //
+ // define local variables
+ //
+
+ BOOLEAN IniOk = TRUE; // initialization status
+ PEISA_DMA_INFO pDmaInfo; // DMA info pointer
+ PEISA_INT_INFO pIntInfo; // INT info pointer
+ PEISA_PORT_INFO pPortInfo; // PORT info pointer
+ PUCHAR EisaIoStart; // EISA I/O virtual address
+
+ PRINTDBG("EisaBusPod\n\r"); // DEBUG SUPPORT
+
+ //
+ // initialize variables
+ //
+
+ pDmaInfo = EisaBusInfo[ BusNumber ].DmaInfo;
+ pIntInfo = EisaBusInfo[ BusNumber ].IntInfo;
+ pPortInfo = EisaBusInfo[ BusNumber ].PortInfo;
+ EisaIoStart = EisaBusInfo[ BusNumber ].IoBusInfo->VirAddr;
+
+ //
+ // perform any PIC testing and initialization
+ //
+
+ if ( !EisaIntPod( EisaIoStart, pIntInfo ) )
+ {
+ IniOk = FALSE;
+ }
+
+ //
+ // perform any DMA testing and initialization
+ //
+
+ if ( !EisaDmaPod( EisaIoStart, pDmaInfo ) )
+ {
+ IniOk = FALSE;
+ }
+
+ //
+ // perform any other port testing and initialization
+ //
+
+ if ( !EisaOtherPod( EisaIoStart, pPortInfo ) )
+ {
+ IniOk = FALSE;
+ }
+
+ //
+ // return status
+ //
+
+ return IniOk;
+}
+
+
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaIntPod:
+//
+// DESCRIPTION: This function tests and initializes the PIC for the
+// specified EISA bus.
+//
+// ARGUMENTS: EisaIoStart EISA I/O virtual address
+// pIntInfo Interrupt info pointer
+//
+// RETURN: TRUE All done
+// FALSE Error
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+//
+// ----------------------------------------------------------------------------
+//
+
+BOOLEAN
+EisaIntPod
+ (
+ IN PUCHAR EisaIoStart,
+ IN PEISA_INT_INFO pIntInfo
+ )
+{
+ PRINTDBG("EisaIntPod\n\r"); // DEBUG SUPPORT
+
+ //
+ // if ini already done, return status
+ //
+
+ if ( pIntInfo->Flags.IniDone )
+ {
+ return (BOOLEAN)(pIntInfo->Flags.Error);
+ }
+ pIntInfo->Flags.Error = 1; // be pessimistic
+
+ //
+ // first part of checkpoint
+ //
+
+ EisaCheckpointFirstFase( EisaPic );
+
+ // NOTE: Interrupts are disabled for Jensen firmware.
+#if 0
+ //
+ // disable EISA PICs interrupt chain
+ //
+
+ EisaDisableInt();
+#endif
+
+
+ do
+ {
+ //
+ // initialize PICs
+ //
+
+ EisaPicIni( EisaIoStart, pIntInfo );
+
+ //
+ // test registers
+ //
+
+ if ( !EisaPicRegTest( EisaIoStart, pIntInfo ));
+
+ //
+ // clear any pending interrupt
+ //
+
+ else if ( !EisaClearPendingInts( EisaIoStart, pIntInfo ));
+
+ //
+ // all done
+ //
+
+ else
+ {
+ pIntInfo->IrqPresent = 0;
+ pIntInfo->IrqShareable = 0;
+ pIntInfo->IrqLevel = 0;
+ pIntInfo->Flags.Error = 0;
+ }
+ }
+ while ( EisaCheckpointFinalFase( EisaPic,
+ pIntInfo->Flags.Error ? FALSE : TRUE ));
+
+ //
+ // return to caller
+ //
+
+ pIntInfo->Flags.IniDone = 1;
+ return !(BOOLEAN)(pIntInfo->Flags.Error);
+}
+
+
+
+
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaPicIni:
+//
+// DESCRIPTION: This function initializes the PICs of the specified
+// EISA bus.
+//
+// ARGUMENTS: EisaIoStart EISA I/O virtual address
+// pIntInfo Interrupt info pointer
+//
+// RETURN: none
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+//
+// ----------------------------------------------------------------------------
+//
+
+VOID
+EisaPicIni
+ (
+ IN PUCHAR EisaIoStart,
+ IN PEISA_INT_INFO pIntInfo
+ )
+{
+ PUCHAR Pic1Port1, Pic1Port2, Pic2Port1, Pic2Port2;
+
+
+ PRINTDBG("EisaPicIni\n\r"); // DEBUG SUPPORT
+
+ //
+ // initialize variables
+ //
+
+ Pic1Port1 = EisaIoStart + PIC1;
+ Pic1Port2 = EisaIoStart + PIC1 + 1;
+ Pic2Port1 = EisaIoStart + PIC2;
+ Pic2Port2 = EisaIoStart + PIC2 + 1;
+
+ //
+ // Initialize the EISA interrupt controller. There are two cascaded
+ // interrupt controllers, each of which must initialized with 4 initialize
+ // control words.
+ //
+
+ EisaOutUchar( Pic1Port1, 0x11 );
+ EisaOutUchar( Pic2Port1, 0x11 );
+
+ //
+ // The second intitialization control word sets the iterrupt vector to
+ // 0-15.
+ //
+
+ EisaOutUchar( Pic1Port2, 0x00 );
+ EisaOutUchar( Pic2Port2, 0x08 );
+
+ //
+ // The thrid initialization control word set the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a numberic.
+ //
+
+ EisaOutUchar( Pic1Port2, 0x04 );
+ EisaOutUchar( Pic2Port2, 0x02 );
+
+ //
+ // The fourth initialization control word is used to specify normal
+ // end-of-interrupt mode and not special-fully-nested mode.
+ //
+
+ EisaOutUchar( Pic1Port2, 0x01 );
+ EisaOutUchar( Pic2Port2, 0x01 );
+
+ //
+ // Mask all the interrupts.
+ //
+
+ EisaOutUchar( Pic1Port2, 0xFF );
+ EisaOutUchar( Pic2Port2, 0xFF );
+
+ //
+ // set all interrupts to edge sensitive
+ //
+
+ EisaOutUchar( EisaIoStart + PIC1_ELCR, 0 );
+ EisaOutUchar( EisaIoStart + PIC2_ELCR, 0 );
+
+ return;
+}
+
+
+
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaPicRegTest:
+//
+// DESCRIPTION: This function performs a test on the PIC registers.
+//
+// ARGUMENTS: EisaIoStart EISA I/O virtual address
+// pIntInfo Interrupt info pointer
+//
+// RETURN: TRUE all correct
+// FALSE error
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+//
+// ----------------------------------------------------------------------------
+//
+
+BOOLEAN
+EisaPicRegTest
+ (
+ IN PUCHAR EisaIoStart,
+ IN PEISA_INT_INFO pIntInfo
+ )
+{
+ //
+ // initialize variables
+ //
+
+ BOOLEAN RegOk = FALSE; // be pessimistic
+
+ PRINTDBG("EisaPicRegTest\n\r"); // DEBUG SUPPORT
+
+ //
+ // check mask of 1st PIC
+ //
+
+ if ( !EisaCheckReg( EisaIoStart + PIC1_MASK, 0xFF ));
+
+ //
+ // check mask of 2nd PIC
+ //
+
+ else if ( !EisaCheckReg( EisaIoStart + PIC2_MASK, 0xFF ));
+
+ //
+ // check ELCR 1, but skip bits 0, 1 and 2 (they are reserved)
+ //
+
+ else if ( !EisaCheckReg( EisaIoStart + PIC1_ELCR, 0xF8 ));
+
+ //
+ // check ELCR 2, but skip bits 0 and 5 (they are reserved)
+ //
+
+ else if ( !EisaCheckReg( EisaIoStart + PIC2_ELCR, 0xDE ));
+
+ //
+ // if we got here, everything is fine
+ //
+
+ else
+ {
+ EisaOutUchar( EisaIoStart + PIC1_MASK, 0xFF );
+ EisaOutUchar( EisaIoStart + PIC2_MASK, 0xFF );
+ EisaOutUchar( EisaIoStart + PIC1_ELCR, 0 );
+ EisaOutUchar( EisaIoStart + PIC2_ELCR, 0 );
+ RegOk = TRUE;
+ }
+
+ return RegOk;
+}
+
+
+
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaClearPendingInts:
+//
+// DESCRIPTION: This function cleares any pending interrupt at
+// the CPU level.
+//
+// ARGUMENTS: EisaIoStart EISA I/O virtual address
+// pIntInfo Interrupt info pointer
+//
+// RETURN: TRUE all correct
+// FALSE error
+//
+// ASSUMPTIONS: interrupts disabled, PIC lines masked and
+// all the IRQ lines are edge triggered.
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+//
+// ----------------------------------------------------------------------------
+//
+
+BOOLEAN
+EisaClearPendingInts
+ (
+ IN PUCHAR EisaIoStart,
+ IN PEISA_INT_INFO pIntInfo
+ )
+{
+ //
+ // initialize variables
+ //
+
+ UCHAR Irr; // interrupt request register
+ UCHAR Isr; // interrupt service register
+ USHORT Irq; // interrupt level
+ PUCHAR PicPort; // I/O address
+
+ PRINTDBG("EisaClearPendingInts\n\r"); // DEBUG SUPPORT
+
+ //--------------------------------------------------
+ // send a specific EOI for each in service interrupt
+ //--------------------------------------------------
+
+ //
+ // read ISR PIC1
+ //
+
+ PicPort = EisaIoStart + PIC1;
+ EisaOutUchar( PicPort, OCW3_ISR );
+ Isr = EisaInUchar( PicPort );
+
+ //
+ // send SEOI for each interrupt that was in service
+ //
+
+ for ( Irq=IRQ0; Isr; Irq++, Isr >>= 1 )
+ {
+ //
+ // check if this IRQ was in service
+ //
+
+ if ( !(Isr & 0x1) )
+ {
+ continue;
+ }
+
+ //
+ // send a specific and of interrupt
+ //
+
+ EisaSendSpecificEoi( EisaIoStart, Irq );
+ }
+
+ //
+ // read ISR PIC2
+ //
+
+ PicPort = EisaIoStart + PIC2;
+ EisaOutUchar( PicPort, OCW3_ISR );
+ Isr = EisaInUchar( PicPort );
+
+ //
+ // send SEOI for each interrupt that was in service
+ //
+
+ for ( Irq=IRQ8; Isr; Irq++, Isr >>= 1 )
+ {
+ //
+ // check if this IRQ was in service
+ //
+
+ if ( !(Isr & 0x1) )
+ {
+ continue;
+ }
+
+ //
+ // send a specific and of interrupt
+ //
+
+ EisaSendSpecificEoi( EisaIoStart, Irq );
+ }
+
+ //--------------------------------------------------
+ // reset all the pending interrupt in the EISA bus
+ //--------------------------------------------------
+
+ //
+ // read IRR PIC1
+ //
+
+ PicPort = EisaIoStart + PIC1;
+ EisaOutUchar( PicPort, OCW3_IRR );
+
+ // don't play with IRQ 0, 1 and 2
+
+ Irr = EisaInUchar( PicPort ) & 0xF8;
+
+ //
+ // clear any PIC1 pending interrupt
+ //
+
+ for ( Irq=IRQ0; Irr; Irq++, Irr >>= 1 )
+ {
+ //
+ // check if this IRQ was pending
+ //
+
+ if ( !(Irr & 0x1) )
+ {
+ continue;
+ }
+
+ //
+ // reset the specified IRQ
+ //
+
+ EisaClearPendingInt( EisaIoStart, pIntInfo, Irq );
+ }
+
+ //
+ // read IRR PIC2
+ //
+
+ PicPort = EisaIoStart + PIC2;
+ EisaOutUchar( PicPort, OCW3_IRR );
+
+ // don't play with IRQ 8
+
+ Irr = EisaInUchar( PicPort ) & 0xFE;
+
+ //
+ // clear any PIC1 pending interrupt
+ //
+
+ for ( Irq=IRQ8; Irr; Irq++, Irr >>= 1 )
+ {
+ //
+ // check if this IRQ was pending
+ //
+
+ if ( !(Irr & 0x1) )
+ {
+ continue;
+ }
+
+ //
+ // reset the specifed IRQ
+ //
+
+ EisaClearPendingInt( EisaIoStart, pIntInfo, Irq );
+ }
+
+ //----------------------------------------------------
+ // error if it is possible to acknowledge an interrupt
+ //----------------------------------------------------
+
+ EisaAckInt( pIntInfo );
+
+ //
+ // read the ISR
+ //
+
+ PicPort = EisaIoStart + PIC1;
+ EisaOutUchar( PicPort, OCW3_ISR );
+
+ return EisaInUchar( PicPort ) ? FALSE : TRUE;
+}
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaDmaPod:
+//
+// DESCRIPTION: This function tests and initializes the DMA for the
+// specified EISA bus.
+//
+// ARGUMENTS: EisaIoStart EISA I/O virtual address
+// pDmaInfo DMA info pointer
+//
+// RETURN: TRUE All done
+// FALSE Error
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+//
+// ----------------------------------------------------------------------------
+//
+
+BOOLEAN
+EisaDmaPod
+ (
+ IN PUCHAR EisaIoStart,
+ IN PEISA_DMA_INFO pDmaInfo
+ )
+{
+ PRINTDBG("EisaDmaPod\n\r"); // DEBUG SUPPORT
+
+ //
+ // if ini already done, return status
+ //
+
+ if ( pDmaInfo->Flags.IniDone )
+ {
+ return (BOOLEAN)(pDmaInfo->Flags.Error);
+ }
+ pDmaInfo->Flags.Error = 1; // be pessimistic
+
+
+ do
+ {
+ //
+ // first part of checkpoint
+ //
+
+ EisaCheckpointFirstFase( EisaDma );
+
+ //
+ // Clear the DMA controllers and disable all the channels.
+ //
+
+ EisaOutUchar( EisaIoStart + DMA_MASTER_CLR03, 0);
+ EisaOutUchar( EisaIoStart + DMA_COMMAND03, 4); // Set channel 0-3 disable
+ EisaOutUchar( EisaIoStart + DMA_MASTER_CLR47, 0);
+ EisaOutUchar( EisaIoStart + DMA_COMMAND47, 4); // Set channel 4-7 disable
+
+ //
+ // check mask register
+ //
+
+ if ( !EisaDmaMaskTest( EisaIoStart, pDmaInfo ));
+
+ //
+ // check the low and high page
+ //
+
+ else if ( !EisaDmaPageTest( EisaIoStart, pDmaInfo ));
+
+ //
+ // check the base/current address register
+ //
+
+ else if ( !EisaDmaAddressTest( EisaIoStart, pDmaInfo ));
+
+ //
+ // check the count register
+ //
+
+ else if ( !EisaDmaCountTest( EisaIoStart, pDmaInfo ));
+
+ //
+ // check stop register
+ //
+
+ else if ( !EisaDmaStopTest( EisaIoStart, pDmaInfo ));
+
+ //
+ // if we got here everything is fine
+ //
+
+ else
+ {
+ EisaDmaIni( EisaIoStart, pDmaInfo );
+ pDmaInfo->Flags.Error = 0;
+ }
+ }
+ while ( EisaCheckpointFinalFase( EisaDma,
+ pDmaInfo->Flags.Error ? FALSE : TRUE ));
+ //
+ // return to caller
+ //
+
+ pDmaInfo->Flags.IniDone = 1;
+ return !(BOOLEAN)(pDmaInfo->Flags.Error);
+}
+
+
+
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaDmaMaskTest:
+//
+// DESCRIPTION: This function tests the mask register.
+//
+// ARGUMENTS: EisaIoStart EISA I/O virtual address
+// pDmaInfo DMA info pointer
+//
+// RETURN: TRUE All done
+// FALSE Error
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES: if any error, all DMA channels will be masked.
+// if no error, all DMA channels will be masked except
+// for channel 4 which is used to cascade the two DMA
+// controllers.
+//
+// ----------------------------------------------------------------------------
+//
+
+BOOLEAN
+EisaDmaMaskTest
+ (
+ IN PUCHAR EisaIoStart,
+ IN PEISA_DMA_INFO pDmaInfo
+ )
+{
+ //
+ // define local variables
+ //
+
+ UCHAR DmaIndex; // DMA channel within controller
+ ULONG DmaCtrl = 0; // DMA controller
+ PUCHAR Clear, MaskAll, Mask, MaskStatus; // port address
+ BOOLEAN CheckOk = TRUE; // check status
+
+ PRINTDBG("EisaDmaMaskTest\n\r"); // DEBUG SUPPORT
+
+ //
+ // one loop per DMA controller
+ //
+
+ do
+ {
+ //
+ // initialize port values
+ //
+
+ Clear = EisaIoStart + EisaDmaCtrlTest[ DmaCtrl ].Clear;
+ MaskAll = EisaIoStart + EisaDmaCtrlTest[ DmaCtrl ].MaskAll;
+ Mask = EisaIoStart + EisaDmaCtrlTest[ DmaCtrl ].Mask;
+ MaskStatus = EisaIoStart + EisaDmaCtrlTest[ DmaCtrl ].MaskStatus;
+
+ //
+ // test mask clear register
+ //
+
+ EisaOutUchar( Clear, 0x00 );
+ if ( EisaInUchar( MaskStatus ) & 0xF )
+ {
+ CheckOk = FALSE;
+ break;
+ }
+
+ //
+ // now set all the mask bits
+ //
+
+ EisaOutUchar( MaskAll, 0x0F );
+ if ( (EisaInUchar( MaskStatus ) & 0x0F) != 0x0F )
+ {
+ CheckOk = FALSE;
+ break;
+ }
+
+ //
+ // now test each single mask bit
+ //
+
+ for ( DmaIndex=0; DmaIndex < 4; DmaIndex++ )
+ {
+ //
+ // clear single bit
+ //
+
+ EisaOutUchar( Mask, DmaIndex );
+ if ( EisaInUchar( MaskStatus ) & (1 << DmaIndex))
+ {
+ CheckOk = FALSE;
+ break;
+ }
+
+ //
+ // set single bit
+ //
+
+ EisaOutUchar( Mask, 0x04 | DmaIndex );
+ if ( !(EisaInUchar( MaskStatus ) & (1 << DmaIndex)))
+ {
+ CheckOk = FALSE;
+ break;
+ }
+ }
+ }
+ while( CheckOk && !DmaCtrl++ );
+
+ //
+ // return check status
+ //
+
+ EisaOutUchar( EisaIoStart + DMA_MASKS03, 0x0F );
+ EisaOutUchar( EisaIoStart + DMA_MASKS47, CheckOk ? 0x0E : 0x0F );
+
+ return CheckOk;
+}
+
+
+
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaDmaPageTest:
+//
+// DESCRIPTION: This function tests the low and high pages.
+//
+// ARGUMENTS: EisaIoStart EISA I/O virtual address
+// pDmaInfo DMA info pointer
+//
+// RETURN: TRUE All done
+// FALSE Error
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES: The low and high page registers will be left in
+// the power-on state of 0x00.
+//
+// ----------------------------------------------------------------------------
+//
+
+BOOLEAN
+EisaDmaPageTest
+ (
+ IN PUCHAR EisaIoStart,
+ IN PEISA_DMA_INFO pDmaInfo
+ )
+{
+ //
+ // define local variables
+ //
+
+ ULONG DmaChannel; // # of DMA channel
+ PUCHAR Port1, Port2; // general I/O ports
+ BOOLEAN CheckOk = TRUE; // check status
+
+ PRINTDBG("EisaDmaPageTest\n\r"); // DEBUG SUPPORT
+
+ //
+ // one loop per DMA channel
+ //
+
+ for ( DmaChannel = 0; DmaChannel < EISA_DMAS; DmaChannel++ )
+ {
+
+ Port1 = EisaIoStart + EisaDmaRegsTest[ DmaChannel ].LowPage;
+ Port2 = EisaIoStart + EisaDmaRegsTest[ DmaChannel ].HighPage;
+
+ //
+ // check high page address
+ //
+
+ if ( DmaChannel != 4 )
+ {
+ EisaOutUchar( Port2, 0xFF );
+
+ if ( !EisaCheckReg( Port2, 0xFF ) )
+ {
+ //
+ // error
+ //
+
+ CheckOk = FALSE;
+ break;
+ }
+ }
+
+ //
+ // check low page register
+ //
+
+ EisaOutUchar( Port1, 0x00 );
+
+ if ( !EisaCheckReg( Port1, 0xFF ) )
+ {
+ //
+ // error
+ //
+
+ CheckOk = FALSE;
+ break;
+ }
+
+ //
+ // check if high reg has been cleared writing to low reg
+ //
+
+ if ( DmaChannel != 4 && EisaInUchar( Port2 ) != 0 )
+ {
+ //
+ // error
+ //
+
+ CheckOk = FALSE;
+ break;
+ }
+ }
+
+ //
+ // return check status
+ //
+
+ return CheckOk;
+}
+
+
+
+
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaDmaAddressTest:
+//
+// DESCRIPTION: This function tests the address register.
+//
+// ARGUMENTS: EisaIoStart EISA I/O virtual address
+// pDmaInfo DMA info pointer
+//
+// RETURN: TRUE All done
+// FALSE Error
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES: The address registers will be left in the power-on
+// state of 0x0000.
+//
+// ----------------------------------------------------------------------------
+//
+
+BOOLEAN
+EisaDmaAddressTest
+ (
+ IN PUCHAR EisaIoStart,
+ IN PEISA_DMA_INFO pDmaInfo
+ )
+{
+ //
+ // define local variables
+ //
+
+ ULONG DmaChannel; // # of DMA channel
+ PUCHAR Port1, Port2; // general I/O ports
+ BOOLEAN CheckOk = TRUE; // check status
+
+ PRINTDBG("EisaDmaAddressTest\n\r"); // DEBUG SUPPORT
+
+ //
+ // reset the internal DMA pointers
+ //
+
+ EisaOutUchar( EisaIoStart + DMA_FF_CLR03, 0x00 );
+ EisaOutUchar( EisaIoStart + DMA_FF_CLR47, 0x00 );
+
+ //
+ // one loop per DMA channel
+ //
+
+ for ( DmaChannel = 0; DmaChannel < EISA_DMAS; DmaChannel++ )
+ {
+ //
+ // load high and address register addresses
+ //
+
+ Port1 = EisaIoStart + EisaDmaRegsTest[ DmaChannel ].Address;
+ Port2 = EisaIoStart + EisaDmaRegsTest[ DmaChannel ].HighPage;
+
+ //
+ // write a value different from zero in high page
+ //
+
+ if ( DmaChannel != 4 )
+ {
+ EisaOutUchar( Port2, 0xFF );
+ }
+
+ //
+ // check word register using one 8 bit port
+ //
+
+ if ( !EisaCheckDeepReg( Port1 ) )
+ {
+ //
+ // error
+ //
+
+ CheckOk = FALSE;
+ break;
+ }
+
+ //
+ // initialize register
+ //
+
+ EisaOutUchar( Port1, 0x00 );
+ EisaOutUchar( Port1, 0x00 );
+
+ //
+ // check if high reg has been cleared writing to low reg
+ //
+
+ if ( DmaChannel != 4 && EisaInUchar( Port2 ) != 0 )
+ {
+ //
+ // error
+ //
+
+ CheckOk = FALSE;
+ break;
+ }
+ }
+
+ //
+ // return check status
+ //
+
+ return CheckOk;
+}
+
+
+
+
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaDmaCountTest:
+//
+// DESCRIPTION: This function tests the count register.
+//
+// ARGUMENTS: EisaIoStart EISA I/O virtual address
+// pDmaInfo DMA info pointer
+//
+// RETURN: TRUE All done
+// FALSE Error
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES: The count registers will be left in the power-on
+// state of 0x00 (high) and 0xFFFF (low).
+//
+// ----------------------------------------------------------------------------
+//
+
+BOOLEAN
+EisaDmaCountTest
+ (
+ IN PUCHAR EisaIoStart,
+ IN PEISA_DMA_INFO pDmaInfo
+ )
+{
+ //
+ // define local variables
+ //
+
+ ULONG DmaChannel; // # of DMA channel
+ PUCHAR Port1, Port2; // general I/O ports
+ BOOLEAN CheckOk = TRUE; // check status
+
+ PRINTDBG("EisaDmaCountTest\n\r"); // DEBUG SUPPORT
+
+ //
+ // reset the internal DMA pointers
+ //
+
+ EisaOutUchar( EisaIoStart + DMA_FF_CLR03, 0x00 );
+ EisaOutUchar( EisaIoStart + DMA_FF_CLR47, 0x00 );
+
+ //
+ // one loop per DMA channel
+ //
+
+ for ( DmaChannel = 0; DmaChannel < EISA_DMAS; DmaChannel++ )
+ {
+ //
+ // load high and address register addresses
+ //
+
+ Port1 = EisaIoStart + EisaDmaRegsTest[ DmaChannel ].LowCount;
+ Port2 = EisaIoStart + EisaDmaRegsTest[ DmaChannel ].HighCount;
+
+ //
+ // check high count register
+ //
+
+ if ( DmaChannel != 4 )
+ {
+ EisaOutUchar( Port2, 0xFF );
+
+ if ( !EisaCheckReg( Port2, 0xFF ) )
+ {
+ //
+ // error
+ //
+
+ CheckOk = FALSE;
+ break;
+ }
+ }
+
+ //
+ // check word register using one 8 bit port
+ //
+
+ if ( !EisaCheckDeepReg( Port1 ) )
+ {
+ //
+ // error
+ //
+
+ CheckOk = FALSE;
+ break;
+ }
+
+ //
+ // initialize register
+ //
+
+ EisaOutUchar( Port1, 0xFF );
+ EisaOutUchar( Port1, 0xFF );
+
+ //
+ // check if high reg has been cleared writing to low reg
+ //
+
+ if ( DmaChannel != 4 && EisaInUchar( Port2 ) != 0 )
+ {
+ //
+ // error
+ //
+
+ CheckOk = FALSE;
+ break;
+ }
+ }
+
+ //
+ // return check status
+ //
+
+ return CheckOk;
+}
+
+
+
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaDmaStopTest:
+//
+// DESCRIPTION: This function tests the stop register.
+//
+// ARGUMENTS: EisaIoStart EISA I/O virtual address
+// pDmaInfo DMA info pointer
+//
+// RETURN: TRUE All done
+// FALSE Error
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES: The count registers will be left in the power-on
+// state of 0xFFFFFC.
+//
+// ----------------------------------------------------------------------------
+//
+
+BOOLEAN
+EisaDmaStopTest
+ (
+ IN PUCHAR EisaIoStart,
+ IN PEISA_DMA_INFO pDmaInfo
+ )
+{
+ //
+ // define local variables
+ //
+
+ ULONG DmaChannel; // # of DMA channel
+ PUCHAR Stop; // general I/O ports
+ BOOLEAN CheckOk = TRUE; // check status
+
+ PRINTDBG("EisaDmaStopTest\n\r"); // DEBUG SUPPORT
+
+ //
+ // one loop per DMA channel
+ //
+
+ for ( DmaChannel = 0; DmaChannel < EISA_DMAS; DmaChannel++ )
+ {
+
+ Stop = EisaIoStart + EisaDmaRegsTest[ DmaChannel ].Stop;
+
+ //
+ // check high page address
+ //
+
+ if ( DmaChannel != 4 )
+ {
+ //
+ // initialize stop registers and test them
+ //
+
+ EisaOutUchar( Stop, 0x00 );
+ EisaOutUchar( Stop+1, 0x00 );
+ EisaOutUchar( Stop+2, 0x00 );
+
+ if ( !EisaCheckReg( Stop, 0xFC ) ||
+ !EisaCheckReg( Stop+1, 0xFF ) ||
+ !EisaCheckReg( Stop+2, 0xFF ) )
+ {
+ //
+ // error
+ //
+
+ CheckOk = FALSE;
+ break;
+ }
+ }
+ }
+
+ //
+ // return check status
+ //
+
+ return CheckOk;
+}
+
+
+
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaDmaIni:
+//
+// DESCRIPTION: This function initializes the DMA controllers of
+// the specified EISA bus.
+//
+// ARGUMENTS: EisaIoStart EISA I/O virtual address
+// pDmaInfo DMA info pointer
+//
+// RETURN: none
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+//
+// ----------------------------------------------------------------------------
+//
+
+VOID
+EisaDmaIni
+ (
+ IN PUCHAR EisaIoStart,
+ IN PEISA_DMA_INFO pDmaInfo
+ )
+{
+ //
+ // define local variables
+ //
+
+ ULONG Index; // general index
+ ULONG DmaCtrl = 0; // DMA controller
+ UCHAR Reg = 0; // DMA command Register
+ PUCHAR Port; // general port
+
+ PRINTDBG("EisaDmaIni\n\r"); // DEBUG SUPPORT
+
+ //-----------------------------------------------------------------
+ //
+ // set command registers for fixed priority, DREQ active high,
+ // DACK# active low and channels enabled
+ //
+
+ EisaOutUchar( EisaIoStart + DMA_COMMAND03, Reg );
+ EisaOutUchar( EisaIoStart + DMA_COMMAND47, Reg );
+
+ //-----------------------------------------------------------------
+ //
+ // initialize mode register for channel 4. The other channels will
+ // be initializated during the EisaRequestDmaTransfer functions.
+ //
+
+ EisaOutUchar( EisaIoStart + DMA_MODE47, 0xC0 );
+
+ //-----------------------------------------------------------------
+ //
+ // disable the chaining mode
+ //
+
+ do
+ {
+ //
+ // load the controller port address
+ //
+
+ Port = EisaIoStart + EisaDmaCtrlTest[ DmaCtrl ].Chain;
+
+ //
+ // disable chaining mode
+ //
+
+ for ( Index = 0; Index < 4 ; Index++ )
+ {
+ EisaOutUchar( Port, 0x00 );
+ }
+ }
+ while( !DmaCtrl++ );
+
+ //-----------------------------------------------------------------
+ //
+ // initialize DMA structures
+ //
+
+ for ( Index = 0; Index < EISA_DMAS; Index++ )
+ {
+ pDmaInfo->DmaFlags[ Index ].Busy = 0;
+ pDmaInfo->DmaFlags[ Index ].Tc = 0;
+
+ // stop enabled, T-C output, ISA compatible,
+ // 8 bit I/O byte count and DMA channel
+ // (see DMA configuration).
+
+ pDmaInfo->DmaExtReg[ Index ] = Index < 4 ? Index : Index - 4;
+ }
+
+ //
+ // all done
+ //
+
+ return;
+}
+
+
+
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaOtherPod:
+//
+// DESCRIPTION: This function tests and initializes all the general
+// ports of the EISA bus.
+//
+// ARGUMENTS: EisaIoStart EISA I/O virtual address
+// pPortInfo port info pointer
+//
+// RETURN: TRUE All done
+// FALSE Error
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+//
+// ----------------------------------------------------------------------------
+//
+
+BOOLEAN
+EisaOtherPod
+ (
+ IN PUCHAR EisaIoStart,
+ IN PEISA_PORT_INFO pPortInfo
+ )
+{
+ //
+ // define local variables
+ //
+
+ BOOLEAN ChkOk;
+
+ PRINTDBG("EisaOtherPod\n\r"); // DEBUG SUPPORT
+
+ //
+ // if ini already done, return status
+ //
+
+ if ( pPortInfo->Flags.IniDone )
+ {
+ return (BOOLEAN)(pPortInfo->Flags.Error);
+ }
+ pPortInfo->Flags.Error = 0;
+
+ //
+ // check and initialize NMI
+ //
+
+ do
+ {
+ EisaCheckpointFirstFase( EisaNmi );
+ if ( !( ChkOk = EisaNmiTest( EisaIoStart, pPortInfo )))
+ {
+ pPortInfo->Flags.Error = 1;
+ }
+ }
+ while ( EisaCheckpointFinalFase( EisaNmi, ChkOk ));
+
+ //
+ // check and initialize refresh
+ //
+
+ do
+ {
+ EisaCheckpointFirstFase( EisaRefresh );
+ if ( !( ChkOk = EisaRefreshTest( EisaIoStart, pPortInfo )))
+ {
+ pPortInfo->Flags.Error = 1;
+ }
+ }
+ while ( EisaCheckpointFinalFase( EisaRefresh, ChkOk ));
+
+ //
+ // check and initialize port 61
+ //
+
+ do
+ {
+ EisaCheckpointFirstFase( EisaPort61 );
+ if ( !( ChkOk = EisaPort61Test( EisaIoStart, pPortInfo )))
+ {
+ pPortInfo->Flags.Error = 1;
+ }
+ }
+ while ( EisaCheckpointFinalFase( EisaPort61, ChkOk ));
+
+ //
+ // check and initialize timer1
+ //
+
+ do
+ {
+ EisaCheckpointFirstFase( EisaTimer1 );
+ if ( !( ChkOk = EisaTimer1Test( EisaIoStart, pPortInfo )))
+ {
+ pPortInfo->Flags.Error = 1;
+ }
+ }
+ while ( EisaCheckpointFinalFase( EisaTimer1, ChkOk ));
+
+ //
+ // check and initialize timer2
+ //
+
+ do
+ {
+ EisaCheckpointFirstFase( EisaTimer2 );
+ if ( !( ChkOk = EisaTimer2Test( EisaIoStart, pPortInfo )))
+ {
+ pPortInfo->Flags.Error = 1;
+ }
+ }
+ while ( EisaCheckpointFinalFase( EisaTimer2, ChkOk ));
+
+ //
+ // return check status
+ //
+
+ pPortInfo->Flags.IniDone = 1;
+ return !(BOOLEAN)(pPortInfo->Flags.Error);
+}
+
+
+
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaNmiTest:
+//
+// DESCRIPTION: This function tests and initializes the EISA NMI.
+//
+// ARGUMENTS: EisaIoStart EISA I/O virtual address
+// pPortInfo port info pointer
+//
+// RETURN: TRUE All done
+// FALSE Error
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS: EisaNmiFlag
+//
+// NOTES: if any error, the NMI will be disabled (real-time clock)
+// if no error, the NMI will be left enabled but with all
+// the NMI sources disabled.
+//
+// ----------------------------------------------------------------------------
+//
+
+BOOLEAN
+EisaNmiTest
+ (
+ IN PUCHAR EisaIoStart,
+ IN PEISA_PORT_INFO pPortInfo
+ )
+{
+ PRINTDBG("EisaNmiTest\n\r"); // DEBUG SUPPORT
+
+ // NOTE: NMI test is disabled for JAZZ and Jensen.
+#if 0
+ //
+ // install an NMI interrupt handler
+ //
+
+ EisaNmiFlag = FALSE;
+
+ FwInstallIntVector( EISA_NMI_VECTOR, EisaNmiHandlerTest );
+
+ //----------------------------------------------------------------
+ //
+ // disable all the NMI sources
+ // (using the extended NMI status and contrl port and system control port B)
+ //
+
+ EisaOutUchar( EisaIoStart + EISA_SYS_EXT_NMI, 0x00 );
+
+ //
+ // note that the following operation clears any pending parity or I/O check
+ // errors.
+ //
+
+ EisaDisableParityIoCheck( EisaIoStart );
+ EisaEnableNmi( EisaIoStart );
+
+ //
+ // ... wait.
+ //
+
+ ArcEisaStallProcessor( EISA_WAIT_NMI_TEST );
+ EisaDisableNmi( EisaIoStart );
+
+ //
+ // return error if an hot EISA NMI
+ //
+
+ if ( EisaNmiFlag )
+ {
+ return FALSE;
+ }
+
+
+ //----------------------------------------------------------------
+ //
+ // enable all the NMI sources used by the fw
+ //
+
+ EisaOutUchar( EisaIoStart + EISA_SYS_EXT_NMI, EISA_ENABLE_NMI_32 );
+ EisaEnableParityIoCheck( EisaIoStart );
+ EisaEnableNmi( EisaIoStart );
+
+ //
+ // ... wait
+ //
+
+ ArcEisaStallProcessor( EISA_WAIT_NMI_TEST );
+ EisaDisableNmi( EisaIoStart );
+
+ //
+ // return error if an hot EISA NMI
+ //
+
+ if ( EisaNmiFlag )
+ {
+ return FALSE;
+ }
+
+
+ //----------------------------------------------------------------
+ //
+ // enable NMI I/O port and NMI; and force one to come
+ //
+
+ EisaOutUchar( EisaIoStart + EISA_SYS_EXT_NMI, EISA_ENABLE_NMI_IO );
+ EisaEnableNmi( EisaIoStart );
+ EisaOutUchar( EisaIoStart + EISA_SW_NMI_PORT, 0x00 );
+
+ //
+ // ... wait
+ //
+
+ ArcEisaStallProcessor( EISA_WAIT_NMI_TEST );
+ EisaDisableNmi( EisaIoStart );
+
+ //
+ // return an error if not NMI
+ //
+
+ if ( !EisaNmiFlag )
+ {
+ return FALSE;
+ }
+
+ //
+ // enable the NMI and all the NMI sources used by fw
+ // ( the software NMI will be disabled )
+ //
+
+ FwInstallIntVector( EISA_NMI_VECTOR, EisaNmiHandler );
+
+ EisaOutUchar( EisaIoStart + EISA_SYS_EXT_NMI, EISA_ENABLE_NMI_32 );
+ EisaEnableNmi( EisaIoStart );
+
+ //
+ // return
+ //
+
+#endif // 0
+ return TRUE;
+}
+
+
+
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaNmiHandlerTest:
+//
+// DESCRIPTION: This function is the NMI handler during the NMI test.
+//
+// ARGUMENTS: Cause R4000 cause register
+//
+// RETURN: TRUE interrupt recognized
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS: EisaNmi
+//
+// NOTES:
+//
+// ----------------------------------------------------------------------------
+//
+
+#if 0 // This is disabled for Jensen.
+
+BOOLEAN
+EisaNmiHandlerTest
+ (
+ IN ULONG Couse
+ )
+{
+ PRINTDBG("EisaNmiHandlerTest\n\r"); // DEBUG SUPPORT
+ StatusReg( ~STATUS_EISA_NMI, (ULONG)0 );
+ EisaNmiFlag = TRUE;
+ return TRUE;
+}
+
+#endif
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaNmiHandler:
+//
+// DESCRIPTION: This function handles the EISA NMI.
+// An NMI can be caused by :
+//
+// 1) System/Adapter board memory parity error
+// ( port 61h bit 7 set )
+// 2) Adapter I/O channel check error
+// ( port 61h bit 6 set )
+// 3) Fail-Safe Timer (channle 2 or the interval Timer 2)
+// ( port 461h bit 7 set ) - NOT CHECKED *
+// 4) DMA bus timeout error
+// ( port 461h bit 6 set )
+// 5) Write to NMI port 462h
+// ( port 461h bit 5 set ) - NOT CHECKED *
+// 6) Coprocessor exception interrupt - NOT CHECKED *
+//
+// An error message will be displayed indicating the
+// cause of the error and the system will halt.
+// The only allowed operation after an NMI is to reset
+// the machine.
+//
+// * The firmware doesn't enable these NMI sources.
+//
+// ARGUMENTS: Cause R4000 cause register
+//
+// RETURN: TRUE interrupt recognized
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS: EisaBusInfo
+//
+// NOTES:
+//
+// ----------------------------------------------------------------------------
+//
+
+#if 0 // This is disabled on Jensen.
+
+BOOLEAN
+EisaNmiHandler
+ (
+ IN ULONG Couse
+ )
+{
+ //
+ // define local variables
+ //
+
+ PUCHAR EisaIoStart; // eisa I/O virtual address
+ UCHAR NmiData, ExtNmiData; // NMI status
+ ULONG BusNumber = 0; // eisa bus number
+ ULONG Slots; // # slots
+ BOOLEAN NmiPresent; // NMI source status
+
+ PRINTDBG("EisaNmiHandler\n\r"); // DEBUG SUPPORT
+
+ //
+ // disable NMI at CPU level
+ //
+
+ StatusReg( ~STATUS_EISA_NMI, (ULONG)0 );
+
+ //
+ // clear screen and display message
+ //
+
+ FwClearScreen();
+ FwPrint(EISA_HOT_NMI_MSG);
+ EisaCheckpointFirstFase( EisaHotNmi );
+
+ do
+ {
+ //
+ // print eisa bus number
+ //
+
+ FwPrint( EISA_BUS_NUMBER_MSG, BusNumber );
+
+ //
+ // initialize variables
+ //
+
+ EisaIoStart = EisaBusInfo[ BusNumber ].IoBusInfo->VirAddr;
+ Slots = EisaBusInfo[ BusNumber ].SlotsInfo->PhysSlots;
+ NmiPresent = FALSE;
+
+ //
+ // read NMI status
+ //
+
+ NmiData = EisaInUchar( EisaIoStart + EISA_SYS_CTRL_PORTB );
+ ExtNmiData = EisaInUchar( EisaIoStart + EISA_SYS_EXT_NMI );
+
+ //
+ // check if there is a parity error
+ //
+
+ if ( NmiData & EISA_PARITY_STATUS )
+ {
+ EisaParityError( EisaIoStart );
+ NmiPresent = TRUE;
+ }
+
+ //
+ // check if there is a I/O channel check
+ //
+
+ if ( NmiData & EISA_IOCHK_STATUS )
+ {
+ EisaIoChkError( EisaIoStart, Slots );
+ NmiPresent = TRUE;
+ }
+
+ //
+ // check if there is a DMA or bus master timeout error
+ //
+
+ if ( ExtNmiData & EISA_NMI_32_STATUS )
+ {
+ if ( ExtNmiData & EISA_NMI_32_CAUSE )
+ {
+ EisaBusTimeoutError( EisaIoStart, Slots );
+ }
+ else
+ {
+ EisaSlaveTimeoutError( EisaIoStart, Slots );
+ }
+ NmiPresent = TRUE;
+ }
+
+ //
+ // if no NMI for this bus, display "no problem"
+ //
+
+ if ( !NmiPresent )
+ {
+ FwPrint(EISA_NMI_NOT_FOUND_MSG);
+ }
+ }
+ while( ++BusNumber < EISA_BUSES );
+
+ //
+ // print final message and hang
+ //
+
+ EisaCheckpointFinalFase( EisaHotNmi, FALSE );
+ while(1); // just to be sure
+}
+
+#endif
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaParityError:
+//
+// DESCRIPTION: This function displays the error message and
+// returns to the caller without do any other thing.
+//
+// ARGUMENTS: EisaIoStart EISA I/O virtual address
+//
+// RETURN: none
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+//
+// ----------------------------------------------------------------------------
+//
+
+VOID
+EisaParityError
+ (
+ IN PUCHAR EisaIoStart
+ )
+{
+ PRINTDBG("EisaParityError\n\r"); // DEBUG SUPPORT
+
+ EISAErrorFwPrint1( EISA_PARITY_ERROR_MSG, ASCII_CSI );
+
+ return;
+}
+
+
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaIoChkError:
+//
+// DESCRIPTION: This function tries to find the slot in error.
+//
+// ARGUMENTS: EisaIoStart EISA I/O virtual address
+// Slots # slots
+//
+// RETURN: none
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+//
+// ----------------------------------------------------------------------------
+//
+
+VOID
+EisaIoChkError
+ (
+ IN PUCHAR EisaIoStart,
+ IN ULONG Slots
+ )
+{
+ //
+ // define local variabls
+ //
+
+ ULONG AdapId; // adapter ID
+ PUCHAR ExpCtrl; // expansion board ctrl addr
+ UCHAR CtrlBits; // port value
+
+ PRINTDBG("EisaIoChkError\n\r"); // DEBUG SUPPORT
+
+ //
+ // display first message
+ //
+
+ EISAErrorFwPrint1( EISA_IO_CHECK_ERROR_MSG, ASCII_CSI);
+
+ //
+ // check all slots starting from the last one
+ //
+
+ while( --Slots )
+ {
+ //
+ // check if there is an adapter with a readable ID
+ //
+
+ if ( !EisaReadReadyId( EisaIoStart, Slots, &AdapId ) ||
+ AdapId == NO_ADAP_ID )
+ {
+ continue;
+ }
+
+ ExpCtrl = EisaIoStart + 0x1000 * Slots + EXPANSION_BOARD_CTRL_BITS;
+
+ //
+ // test the IOCHKERR bit of the Expansion Board Contrl Bits.
+ // the IOCHKERR bit can be read to determine if an expansion
+ // board has a pending error. The expansion board indicates a
+ // pending error by setting IOCHKERR, clearing the ENABLE bit
+ // and entering the disabled state.
+ //
+ // note: because the EISA expansion boards are not required to
+ // support this port, we need the following simple
+ // assumption: this I/O port is not supported if the value
+ // read from it is 0xFF.
+ //
+
+ if ((CtrlBits = EisaInUchar( ExpCtrl )) != 0xFF )
+ {
+ if ( CtrlBits & EISA_IOCHKERR )
+ {
+ break;
+ }
+ }
+ }
+
+ //
+ // print final message
+ //
+
+ if ( !Slots )
+ {
+ FwPrint( EISA_IO_CHECK_NOT_SUP_MSG ); // slot not found
+ }
+ else
+ {
+ FwPrint( EISA_IN_SLOT_MSG, Slots ); // slot in error
+ }
+
+ //
+ // all done, exit
+ //
+
+ return;
+}
+
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaBusTimeoutError:
+//
+// DESCRIPTION: This function displays the bus master number in error.
+// If a 32-bit bus master tries to hold the bus beyond
+// the BUS limit (8 usec if BCLK = 8 MHz), the ISP will
+// assert the NMI and RSTDRV signals togheter.
+// The RSTDRV signal will remain aserted until the NMI has
+// been reset by plsing bit 3 of I/O port 461h.
+//
+// ARGUMENTS: EisaIoStart EISA I/O virtual address
+// Slots # slots
+//
+// RETURN: none
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+//
+// ----------------------------------------------------------------------------
+//
+
+VOID
+EisaBusTimeoutError
+ (
+ IN PUCHAR EisaIoStart,
+ IN ULONG Slots
+ )
+{
+ //
+ // define local variables
+ //
+
+ UCHAR Status; // 32-bit bus master status
+ ULONG BusMaster = 0; // bus master number in error
+ PUCHAR ExtNmi; // extended NMI control
+
+ PRINTDBG("EisaBusTimeoutError\n\r"); // DEBUG SUPPORT
+
+ //
+ // find the bus master group in error
+ //
+
+ if ( ~(Status = EisaInUchar(EisaIoStart+EISA_BUSMASTER_LSTATUS)) & 0xFF )
+ {
+ BusMaster = 1;
+ }
+ else if ( ~(Status = (EisaInUchar(EisaIoStart+EISA_BUSMASTER_HSTATUS) |
+ 0x80)) & 0xFF )
+ {
+ BusMaster = 9;
+ }
+
+ //
+ // find the bus master number in error and display it
+ //
+
+ EISAErrorFwPrint1( EISA_BUS_MASTER_MSG, ASCII_CSI );
+
+ if ( BusMaster )
+ {
+ for (; Status & 1; Status >>= 1, BusMaster++ );
+ FwPrint( EISA_TIMEOUT_MSG, BusMaster );
+ }
+ else
+ {
+ FwPrint( EISA_TIMEOUT2_MSG ); // bus master not found
+ }
+
+ //
+ // reset NMI
+ //
+
+ ExtNmi = EisaIoStart + EISA_SYS_EXT_NMI;
+ EisaOutUchar( ExtNmi, EisaInUchar( ExtNmi ) & ~EISA_ENABLE_NMI_32 );
+
+ //
+ // all done
+ //
+
+ return;
+}
+
+
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaSlaveTimeoutError:
+//
+// DESCRIPTION: This function displays an error message.
+// If a memory slave extends a cycle long enough that
+// CMD# is active for more than 256 BCLKs (32usec if
+// BCLK = 8MHz), the ISP will assert the NMI and RSTDRV
+// signals togheter.
+// The RSTDRV signal will remain aserted until the NMI has
+// been reset by plsing bit 3 of I/O port 461h.
+//
+// ARGUMENTS: EisaIoStart EISA I/O virtual address
+// Slots # slots
+//
+// RETURN: none
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+//
+// ----------------------------------------------------------------------------
+//
+
+VOID
+EisaSlaveTimeoutError
+ (
+ IN PUCHAR EisaIoStart,
+ IN ULONG Slots
+ )
+{
+ //
+ // define local variables
+ //
+
+ PUCHAR ExtNmi; // extended NMI control
+
+ PRINTDBG("EisaSlaveTimeoutError\n\r"); // DEBUG SUPPORT
+
+ //
+ // display the error message
+ //
+
+ EISAErrorFwPrint1( EISA_SLAVE_TIMEOUT_MSG, ASCII_CSI );
+
+ //
+ // reset NMI
+ //
+
+ ExtNmi = EisaIoStart + EISA_SYS_EXT_NMI;
+ EisaOutUchar( ExtNmi, EisaInUchar( ExtNmi ) & ~EISA_ENABLE_NMI_32 );
+
+ //
+ // all done
+ //
+
+ return;
+}
+
+
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaRefreshTest:
+//
+// DESCRIPTION: This function tests and initializes the EISA refresh.
+//
+// ARGUMENTS: EisaIoStart EISA I/O virtual address
+// pPortInfo port info pointer
+//
+// RETURN: TRUE All done
+// FALSE Error
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES: the refresh will be left enabled.
+//
+// ----------------------------------------------------------------------------
+//
+
+BOOLEAN
+EisaRefreshTest
+ (
+ IN PUCHAR EisaIoStart,
+ IN PEISA_PORT_INFO pPortInfo
+ )
+{
+ //
+ // define local variables
+ //
+
+ BOOLEAN CheckOk = FALSE; // checking status
+ ULONG Retry; // # retry
+ PUCHAR Port; // general I/O port
+
+ PRINTDBG("EisaRefreshTest\n\r"); // DEBUG SUPPORT
+
+ //
+ // clear refresh pages
+ //
+
+ EisaOutUchar( EisaIoStart + DMA_PAGE_RFR, 0x00 );
+ EisaOutUchar( EisaIoStart + DMA_HPAGE_RFR, 0x00 );
+
+ //
+ // start timer 1, counter 1
+ //
+
+ EisaOutUchar( EisaIoStart + EISA_TIMER1_CTRL, 0x54 );
+ EisaOutUchar( EisaIoStart + EISA_TIMER1_COUNTER1, EISA_RFR_COUNT );
+
+ //
+ // check if refresh bit in the system control port B is toggling
+ //
+
+ Port = EisaIoStart + EISA_SYS_CTRL_PORTB;
+
+ for ( CheckOk = FALSE, Retry = EISA_RFR_RETRY; Retry; Retry-- )
+ {
+ //
+ // check if refresh bit is set
+ //
+
+ if ( READ_PORT_UCHAR( Port ) & EISA_REFRESH )
+ {
+ //
+ // yes, exit loop
+ //
+
+ CheckOk = TRUE;
+ break;
+ }
+ }
+
+ //
+ // if time-out, exit with error
+ //
+
+ if ( !Retry )
+ {
+ return FALSE;
+ }
+
+ //
+ // check if refresh bit in the system control port B is toggling
+ //
+
+ for ( CheckOk = FALSE, Retry = EISA_RFR_RETRY; Retry; Retry-- )
+ {
+ //
+ // check if refresh bit is cleared
+ //
+
+ if ( !(READ_PORT_UCHAR( Port ) & EISA_REFRESH) )
+ {
+ //
+ // yes, exit loop
+ //
+
+ CheckOk = TRUE;
+ break;
+ }
+ }
+
+ //
+ // return check status
+ //
+
+ return CheckOk;
+}
+
+
+
+
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaPort61Test:
+//
+// DESCRIPTION: This function tests and initializes the system
+// control port B.
+//
+// ARGUMENTS: EisaIoStart EISA I/O virtual address
+// pPortInfo port info pointer
+//
+// RETURN: TRUE All done
+// FALSE Error
+//
+// ASSUMPTIONS: NMI has already been tested.
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES: The parity and the I/O channel check, The speaker gate
+// and speaker timer will be left disabled.
+//
+// ----------------------------------------------------------------------------
+//
+
+BOOLEAN
+EisaPort61Test
+ (
+ IN PUCHAR EisaIoStart,
+ IN PEISA_PORT_INFO pPortInfo
+ )
+{
+ //
+ // define local variables
+ //
+
+ PUCHAR Port; // genearl I/O port
+ BOOLEAN CheckOk = TRUE; // check status
+
+ PRINTDBG("EisaPort61Test\n\r"); // DEBUG SUPPORT
+
+ Port = EisaIoStart + EISA_SYS_CTRL_PORTB;
+
+ //
+ // gate signal for speaker timer
+ //
+
+ EisaOutUchar( Port, EISA_SPEAKER_GATE );
+ if ( (EisaInUchar( Port ) & 0x0F) != EISA_SPEAKER_GATE )
+ {
+ CheckOk = FALSE;
+ }
+
+ //
+ // speaker timer contrl
+ //
+
+ if ( CheckOk )
+ {
+ EisaOutUchar( Port, EISA_SPEAKER_TIMER);
+ if ( (EisaInUchar( Port ) & 0x0F) != EISA_SPEAKER_TIMER )
+ {
+ CheckOk = FALSE;
+ }
+ }
+
+ //
+ // parity bit
+ //
+
+ if ( CheckOk )
+ {
+ EisaOutUchar( Port, EISA_PARITY_OFF);
+ if ( (EisaInUchar( Port ) & 0x0F) != EISA_PARITY_OFF )
+ {
+ CheckOk = FALSE;
+ }
+ }
+
+ //
+ // I/O channel check
+ //
+
+ if ( CheckOk )
+ {
+ EisaOutUchar( Port, EISA_IOCHK_OFF );
+ if ( (EisaInUchar( Port ) & 0x0F) != EISA_IOCHK_OFF )
+ {
+ CheckOk = FALSE;
+ }
+ }
+
+ //
+ // initialize port 61h.
+ //
+
+ EisaOutUchar( Port, 0x00 );
+
+ //
+ // return check status
+ //
+
+ return CheckOk;
+}
+
+
+
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaTimer1Test:
+//
+// DESCRIPTION: This function tests only the counter 2 of
+// timer 1 (speaker).
+//
+// ARGUMENTS: EisaIoStart EISA I/O virtual address
+// pPortInfo port info pointer
+//
+// RETURN: TRUE All done
+// FALSE Error
+//
+// ASSUMPTIONS: NMI has already been tested.
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES: The functions stops timer1 counter0, turns off the
+// timer1 counter2 gate and disable the speaker output.
+//
+// ----------------------------------------------------------------------------
+//
+
+BOOLEAN
+EisaTimer1Test
+ (
+ IN PUCHAR EisaIoStart,
+ IN PEISA_PORT_INFO pPortInfo
+ )
+{
+ //
+ // define local variables
+ //
+
+ BOOLEAN CheckOk = FALSE; // check status
+ PUCHAR Ctrl, Port, Port61; // genearl I/O ports
+
+ PRINTDBG("EisaTimer1Test\n\r"); // DEBUG SUPPORT
+
+ //
+ // initialize variables
+ //
+
+ Ctrl = EisaIoStart + EISA_TIMER1_CTRL;
+ Port = EisaIoStart + EISA_TIMER1_COUNTER2;
+ Port61 = EisaIoStart + EISA_SYS_CTRL_PORTB;
+
+ //
+ // disable timer1 counter2 gate, speaker output
+ //
+
+ EisaOutUchar( Port61, 0x00 );
+
+ //
+ // program timer 1, counter 2 (speaker) in 16-bit count, mode 0
+ //
+
+ EisaOutUchar( Ctrl, 0xB0 );
+ EisaOutUchar( Port, 0x00 );
+ EisaOutUchar( Port, 0x80 );
+
+ //
+ // check register
+ //
+
+ if ( !(EisaCheckDeepReg( Port )));
+
+ //
+ // check speaker output. It must be low otherwise there is an error
+ //
+
+ else if ( EisaInUchar( Port61 ) & EISA_SPEAKER_OUT );
+
+ //
+ // enable speaker gate to enable the counter, wait for some time and
+ // check if speaker output is high, if not error out
+ //
+
+ else
+ {
+ //
+ // enable speaker gate
+ //
+
+ EisaOutUchar( Port61, EISA_SPEAKER_GATE );
+
+ //
+ // wait 40msec = ~ ( 0x8000 / 1.193 Mhz ) + something
+ //
+
+// NOTE: Wait longer for JAZZ.
+// ArcEisaStallProcessor( 40 * 1000 );
+ ArcEisaStallProcessor( 160 * 1000 );
+
+ //
+ // check speaker output
+ //
+
+ if ( EisaInUchar( Port61 ) & EISA_SPEAKER_OUT )
+ {
+ //
+ // initialize timer1 counter2 in 16-bit , mode 3
+ //
+
+ // EisaOutUchar( Ctrl, 0xB6 );
+ // EisaOutUchar( Port,
+ // (UCHAR)( EISA_SPEAKER_CLOCK/EISA_SPEAKER_FREQ ));
+ // EisaOutUchar( Port,
+ // (UCHAR)( (EISA_SPEAKER_CLOCK/EISA_SPEAKER_FREQ) >> 8 ));
+
+ //
+ // all done
+ //
+
+ CheckOk = TRUE;
+ }
+ }
+
+ //
+ // disable speaker gate, speaker output
+ //
+
+ EisaOutUchar( Port61, 0x00 );
+
+ //
+ // stop timer1 counter0 sending the control word without the count value
+ //
+
+ EisaOutUchar( Ctrl, 0x30 );
+
+ //
+ // all done, exit
+ //
+
+ return CheckOk;
+}
+
+
+
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaTimer2Test:
+//
+// DESCRIPTION: This function stops the timer2 counter0 (Fail-safe).
+//
+// ARGUMENTS: EisaIoStart EISA I/O virtual address
+// pPortInfo port info pointer
+//
+// RETURN: TRUE All done
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+//
+// ----------------------------------------------------------------------------
+//
+
+BOOLEAN
+EisaTimer2Test
+ (
+ IN PUCHAR EisaIoStart,
+ IN PEISA_PORT_INFO pPortInfo
+ )
+{
+ PRINTDBG("EisaTimer2Test\n\r"); // DEBUG SUPPORT
+
+ //
+ // stop timer2 counter0 sending the control word without the count value
+ //
+
+ EisaOutUchar( EisaIoStart + EISA_TIMER2_CTRL, 0x30 );
+
+ //
+ // all done, exit
+ //
+
+ return TRUE;
+}
+
+
+
+
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaClearPendingInt:
+//
+// DESCRIPTION: This function cleares the specified pending interrupt.
+//
+// ARGUMENTS: EisaIoStart EISA I/O virtual address
+// pIntInfo interrupt info pointer
+// Irq IRQ to reset
+//
+// RETURN: none
+//
+// ASSUMPTIONS: none
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+//
+// ----------------------------------------------------------------------------
+//
+
+VOID
+EisaClearPendingInt
+ (
+ IN PUCHAR EisaIoStart,
+ IN PEISA_INT_INFO pIntInfo,
+ IN USHORT Irq
+ )
+{
+ //
+ // define local variables
+ //
+
+ PUCHAR PicMask1, PicMask2; // I/O port address
+
+ PRINTDBG("EisaClearPendingInt\n\r"); // DEBUG SUPPORT
+
+ //
+ // initialize variables
+ //
+
+ PicMask1 = EisaIoStart + PIC1_MASK;
+ PicMask2 = EisaIoStart + PIC2_MASK;
+
+ //
+ // unmask the specified IRQ
+ //
+
+ if ( Irq > IRQ7 )
+ {
+ EisaOutUchar( PicMask1, (UCHAR)(~(1 << IRQ2)));
+ EisaOutUchar( PicMask2, (UCHAR)(~(1 << (Irq % 8))));
+ }
+ else
+ {
+ EisaOutUchar( PicMask1, (UCHAR)(~(1 << Irq )));
+ }
+
+ //
+ // acknowledge the interrupt
+ //
+
+ EisaAckInt( pIntInfo );
+
+ //
+ // mask off all the IRQ lines
+ //
+
+ EisaOutUchar( PicMask1, 0xFF );
+ EisaOutUchar( PicMask2, 0xFF );
+
+ //
+ // and send a specific EOF
+ //
+
+ EisaSendSpecificEoi( EisaIoStart, Irq );
+
+ return;
+}
+
+
+
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaIntAck:
+//
+// DESCRIPTION: This function acknowledges the highest priority
+// interrupt.
+//
+// ARGUMENTS: pIntInfo interrupt info pointer (not used)
+//
+// RETURN: Int interrupt acknowledged.
+//
+// ASSUMPTIONS: none
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+//
+// ----------------------------------------------------------------------------
+//
+
+UCHAR
+EisaAckInt
+ (
+ IN PEISA_INT_INFO pIntInfo
+ )
+{
+ UCHAR Int;
+
+ PRINTDBG("EisaAckInt\n\r"); // DEBUG SUPPORT
+
+ Int = READ_PORT_UCHAR( (PUCHAR)EISA_INT_ACK_ADDR );
+ EISA_IO_DELAY;
+
+ return Int;
+}
+
+
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaSendSpecificEoi:
+//
+// DESCRIPTION: This function sends a specific EOI to the spcified
+// IRQ line.
+//
+// ARGUMENTS: EisaIoStart EISA I/O virtual address
+// Irq IRQ to reset
+//
+// RETURN: none
+//
+// ASSUMPTIONS: none
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+//
+// ----------------------------------------------------------------------------
+//
+
+VOID
+EisaSendSpecificEoi
+ (
+ IN PUCHAR EisaIoStart,
+ IN USHORT Irq
+ )
+{
+ //
+ // define local variables
+ //
+
+ PUCHAR PicPort1, PicPort2;
+
+ PRINTDBG("EisaSendSpecificEoi\n\r"); // DEBUG SUPPORT
+
+ //
+ // initialize local variables
+ //
+
+ PicPort1 = EisaIoStart + PIC1;
+ PicPort2 = EisaIoStart + PIC2;
+
+ //
+ // send a specific EOI
+ //
+
+ if ( Irq > IRQ7 )
+ {
+ EisaOutUchar( PicPort2, OCW2_SEOI | ( Irq % 8 ));
+ EisaOutUchar( PicPort1, OCW2_SEOI | IRQ2 );
+ }
+ else
+ {
+ EisaOutUchar( PicPort1, OCW2_SEOI | Irq );
+ }
+
+ return;
+}
+
+
+
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaDisableParityIoCheck:
+//
+// DESCRIPTION: This function disables the partiy and I/O check NMIs.
+//
+// ARGUMENTS: EisaIoStart EISA I/O virtual address
+//
+// RETURN: none
+//
+// ASSUMPTIONS: none
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+//
+// ----------------------------------------------------------------------------
+//
+
+VOID
+EisaDisableParityIoCheck
+ (
+ IN PUCHAR EisaIoStart
+ )
+{
+ PRINTDBG("EisaDisableParityIoCheck\n\r"); // DEBUG SUPPORT
+
+ EisaOutUchar( EisaIoStart + EISA_SYS_CTRL_PORTB,
+ ( EisaInUchar( EisaIoStart + EISA_SYS_CTRL_PORTB ) |
+ EISA_PARITY_OFF | EISA_IOCHK_OFF ) & 0x0F );
+
+ return;
+}
+
+
+
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaEnableParityIoCheck:
+//
+// DESCRIPTION: This function enables the partiy and I/O check NMIs.
+//
+// ARGUMENTS: EisaIoStart EISA I/O virtual address
+//
+// RETURN: none
+//
+// ASSUMPTIONS: none
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+//
+// ----------------------------------------------------------------------------
+//
+
+VOID
+EisaEnableParityIoCheck
+ (
+ IN PUCHAR EisaIoStart
+ )
+{
+ PRINTDBG("EisaEnableParityIoCheck\n\r"); // DEBUG SUPPORT
+
+ EisaOutUchar( EisaIoStart + EISA_SYS_CTRL_PORTB,
+ ( EisaInUchar( EisaIoStart + EISA_SYS_CTRL_PORTB ) &
+ ~(EISA_PARITY_OFF | EISA_IOCHK_OFF)) & 0x0F );
+
+ return;
+}
+
+
+
+
+
+
+
+
+// NOTE: Not needed in Jensen.
+#if 0
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaDisableInt:
+//
+// DESCRIPTION: The function disables the EISA interrupts at CPU
+// level.
+//
+// ARGUMENTS: none
+//
+// RETURN: none
+//
+// ASSUMPTIONS: none
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+//
+// ----------------------------------------------------------------------------
+//
+
+VOID
+EisaDisableInt
+ (
+ VOID
+ )
+{
+ PRINTDBG("EisaDisableInt\n\r"); // DEBUG SUPPORT
+ StatusReg( ~STATUS_EISA, (ULONG)0 );
+ return;
+}
+
+#endif
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaDisableNmi:
+//
+// DESCRIPTION: The function disables the NMI using the real-time
+// clock port.
+//
+// ARGUMENTS: none
+//
+// RETURN: none
+//
+// ASSUMPTIONS: none
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+//
+// ----------------------------------------------------------------------------
+//
+
+VOID
+EisaDisableNmi
+ (
+ IN PUCHAR EisaIoStart
+ )
+{
+ PRINTDBG("EisaDisableNmi\n\r"); // DEBUG SUPPORT
+
+ //
+ // at real-time clock address port
+ //
+
+ EisaOutUchar(EisaIoStart+EISA_RTC_CTRL, EISA_DISABLE_NMI+RTC_C_REG);
+ READ_PORT_UCHAR( (PUCHAR)RTC_VIRTUAL_BASE );
+
+ return;
+}
+
+
+
+
+
+
+
+// Note: Not needed on Jensen.
+
+#if 0
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaEnableNmi:
+//
+// DESCRIPTION: The function enables the NMI line.
+// The following ports are used :
+//
+// . real-time clock ctrl port
+// . CPU status register port
+//
+// ARGUMENTS: none
+//
+// RETURN: none
+//
+// ASSUMPTIONS: none
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+//
+// ----------------------------------------------------------------------------
+//
+
+VOID
+EisaEnableNmi
+ (
+ IN PUCHAR EisaIoStart
+ )
+{
+ PRINTDBG("EisaEnableNmi\n\r"); // DEBUG SUPPORT
+
+ //
+ // at real-time clock address port
+ //
+ EisaReadRtc( EisaIoStart, RTC_C_REG );
+
+
+// NOTE: this code has been removed because of a R4000 CPU bug.
+//
+// //
+// // at interrupt enable register
+// //
+//
+// EisaBeginCriticalSection();
+// WRITE_PORT_UCHAR(INT_ENABLE_ADDR, READ_PORT_UCHAR(INT_ENABLE_ADDR) | 0x08);
+// EisaEndCriticalSection();
+//
+
+ //
+ // at CPU level
+ //
+ StatusReg( (ULONG)-1, STATUS_EISA_NMI + STATUS_IE );
+ return;
+}
+
+
+
+#endif
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaCheckReg:
+//
+// DESCRIPTION: This function performs read/write test on an 8 bit
+// I/O port using the following patterns: FFh, AAh, 55h
+// and 00h. The original part value is restored before
+// returning.
+//
+// ARGUMENTS: Port port address
+// DataMask mask for test pattern to compare with
+// data
+//
+// RETURN: TRUE test completed successfully
+// FALSE error
+//
+// ASSUMPTIONS: none
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+//
+// ----------------------------------------------------------------------------
+//
+
+BOOLEAN
+EisaCheckReg
+ (
+ IN PUCHAR Port,
+ IN UCHAR DataMask
+ )
+{
+ //
+ // define local variables
+ //
+
+ BOOLEAN CompOk = TRUE;
+ UCHAR Save, Program;
+
+ PRINTDBG("EisaCheckReg\n\r"); // DEBUG SUPPORT
+
+ //
+ // save original value
+ //
+
+ Save = EisaInUchar( Port );
+
+ //
+ // one loop per each value
+ //
+
+ for ( Program = 0; ; Program += 0x55 )
+ {
+ //
+ // write port, read it back and compare values
+ //
+
+ EisaOutUchar( Port, Program );
+
+ if ((EisaInUchar( Port ) & DataMask) != (Program & DataMask))
+ {
+ //
+ // error, value are not the same
+ //
+
+ CompOk = FALSE;
+ break;
+ }
+
+ //
+ // exit loop if last value
+ //
+
+ if ( Program == 0xFF )
+ {
+ break;
+ }
+ }
+
+ //
+ // restore original value before returning
+ //
+
+ EisaOutUchar( Port, Save );
+
+ return CompOk;
+}
+
+
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaCheckDeepReg:
+//
+// DESCRIPTION: This function checks the 2x8bit registers.
+//
+// ARGUMENTS: EisaIoStart EISA I/O virtual address
+// pDmaInfo DMA info pointer
+//
+// RETURN: TRUE check completed successfully
+// FALSE error
+//
+// ASSUMPTIONS: The internal pointer has already been resetted.
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+//
+// ----------------------------------------------------------------------------
+//
+
+BOOLEAN
+EisaCheckDeepReg
+ (
+ IN PUCHAR Port
+ )
+{
+ //
+ // define local variables
+ //
+
+ UCHAR LSave, HSave, Program, LCheck, HCheck;
+ BOOLEAN CompOk = TRUE;
+
+ PRINTDBG("EisaCheckDeepReg\n\r"); // DEBUG SUPPORT
+
+ //
+ // save original value
+ //
+
+ LSave = EisaInUchar( Port );
+ HSave = EisaInUchar( Port );
+
+ //
+ // one loop per each value
+ //
+
+ for ( Program = 0; ; Program += 0x55 )
+ {
+ //
+ // write port and read it back
+ //
+
+ EisaOutUchar( Port, Program );
+ EisaOutUchar( Port, Program );
+
+ EISA_IO_DELAY; //
+ EISA_IO_DELAY; // for the timer chip
+ EISA_IO_DELAY; //
+
+ LCheck = EisaInUchar( Port );
+ HCheck = EisaInUchar( Port );
+
+ //
+ // check the read values
+ //
+
+ if ( LCheck != Program || HCheck != Program )
+ {
+ //
+ // error, value are not the same
+ //
+
+ CompOk = FALSE;
+ break;
+ }
+
+ //
+ // exit loop if last value
+ //
+
+ if ( Program == 0xFF )
+ {
+ break;
+ }
+ }
+
+ //
+ // restore the original value
+ //
+
+ EisaOutUchar( Port, LSave );
+ EisaOutUchar( Port, HSave );
+
+ return CompOk;
+}
+
+
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaReadRtc:
+//
+// DESCRIPTION: This function returns the value of the specified
+// real-time clock internal address.
+//
+// ARGUMENTS: EisaIoStart EISA I/O virtual address
+// RtcIndex index within the RTC
+//
+// RETURN: Value register value
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+//
+// ----------------------------------------------------------------------------
+//
+
+UCHAR
+EisaReadRtc
+ (
+ IN PUCHAR EisaIoStart,
+ IN ULONG RtcIndex
+ )
+{
+ UCHAR Value;
+
+ PRINTDBG("EisaReadRtc\n\r"); // DEBUG SUPPORT
+
+// NOTE: CriticalSection is not supported on JAZZ.
+// EisaBeginCriticalSection();
+ EisaOutUchar( EisaIoStart + EISA_RTC_CTRL, RtcIndex );
+ Value = READ_PORT_UCHAR( (PUCHAR)RTC_VIRTUAL_BASE );
+// EisaEndCriticalSection();
+
+ return Value;
+}
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaOutUchar:
+//
+// DESCRIPTION: This function writes an uchar within the EISA I/O
+// space and delays before returning.
+//
+// ARGUMENTS: Addr Address where the value has to be
+// write to.
+// Value Value to write
+//
+// RETURN: none
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+//
+// ----------------------------------------------------------------------------
+//
+
+VOID
+EisaOutUchar
+ (
+ IN PUCHAR Addr,
+ IN UCHAR Value
+ )
+{
+// PRINTDBG("EisaOutUchar\n\r"); // DEBUG SUPPORT
+
+ WRITE_PORT_UCHAR( Addr, Value );
+ EISA_IO_DELAY;
+
+ return;
+}
+
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: EisaInUchar:
+//
+// DESCRIPTION: This function reads an uchar from the EISA I/O
+// space and delays before returning.
+//
+// This does an EISAReadPortUCHAR call so that reads
+// to the system board ID can be trapped by the firmware
+// on certain Alpha AXP machines.
+//
+// ARGUMENTS: Addr Address where the value has to be
+// read from.
+//
+// RETURN: none
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+//
+// ----------------------------------------------------------------------------
+//
+
+UCHAR
+EisaInUchar
+ (
+ IN PUCHAR Addr
+ )
+{
+ UCHAR Value;
+
+// PRINTDBG("EisaInUchar\n\r"); // DEBUG SUPPORT
+
+// Value = READ_PORT_UCHAR( Addr );
+ Value = EISAReadPortUCHAR( 0, (ULONG)Addr );
+ EISA_IO_DELAY;
+
+ return Value;
+}
+
+
diff --git a/private/ntos/fw/alpha/eisastr.h b/private/ntos/fw/alpha/eisastr.h
new file mode 100644
index 000000000..edda28ff6
--- /dev/null
+++ b/private/ntos/fw/alpha/eisastr.h
@@ -0,0 +1,39 @@
+//
+// Common strings.
+//
+
+extern PCHAR EISA_OK_MSG;
+extern PCHAR EISA_CRLF_MSG;
+extern PCHAR EISA_ERROR1_MSG;
+
+//
+// Eisa strings.
+//
+
+// ----------------------------------------------------------------------------
+// GLOBAL: EISA error messages
+// ----------------------------------------------------------------------------
+//
+// 1 2 3 4 5 6 7
+// 01234567890123456789012345678901234567890123456789012345678901234567890
+
+extern PCHAR EisaCfgMessages[];
+
+extern EISA_CHECKPOINT_INFO EisaCheckpointInfo[];
+
+extern PCHAR EISA_INIT_MSG;
+extern PCHAR EISA_BUS_MSG;
+extern PCHAR EISA_ERROR_SLOT_MSG;
+extern PCHAR EISA_HOT_NMI_MSG;
+extern PCHAR EISA_BUS_NUMBER_MSG;
+extern PCHAR EISA_NMI_NOT_FOUND_MSG;
+extern PCHAR EISA_PARITY_ERROR_MSG;
+extern PCHAR EISA_IO_CHECK_ERROR_MSG;
+extern PCHAR EISA_IO_CHECK_NOT_SUP_MSG;
+extern PCHAR EISA_IN_SLOT_MSG;
+extern PCHAR EISA_BUS_MASTER_MSG;
+extern PCHAR EISA_TIMEOUT_MSG;
+extern PCHAR EISA_TIMEOUT2_MSG;
+extern PCHAR EISA_SLAVE_TIMEOUT_MSG;
+extern PCHAR EISA_CANT_MARK_BUFFER_MSG;
+extern PCHAR EISA_BAD_INDEX_MSG;
diff --git a/private/ntos/fw/alpha/eisausa.c b/private/ntos/fw/alpha/eisausa.c
new file mode 100644
index 000000000..dd7aadfa2
--- /dev/null
+++ b/private/ntos/fw/alpha/eisausa.c
@@ -0,0 +1,102 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ eisausa.c
+
+Abstract:
+
+ This module contains the eisa english strings.
+
+Author:
+
+ David M. Robinson (davidro) 21-May-1993
+
+
+Revision History:
+
+
+--*/
+
+#include "ntos.h"
+#include "oli2msft.h"
+#include "inc.h"
+
+//
+// Common strings.
+//
+
+PCHAR EISA_OK_MSG = "OK.";
+PCHAR EISA_CRLF_MSG = "\r\n";
+PCHAR EISA_ERROR1_MSG = "Error";
+
+//
+// Eisa strings.
+//
+
+// ----------------------------------------------------------------------------
+// GLOBAL: EISA error messages
+// ----------------------------------------------------------------------------
+//
+// 1 2 3 4 5 6 7
+// 01234567890123456789012345678901234567890123456789012345678901234567890
+
+PCHAR EisaCfgMessages[] = {
+ "Invalid Message",
+ "ID Timeout",
+ "ID Configuration",
+ "Missing Configuration",
+ "Incomplete Configuration",
+ "Configuration",
+ "Failed Bit Set",
+ "Memory Configuration",
+ "IRQ Configuration",
+ "DMA Configuration",
+ "Port Configuration",
+ "OMF ROM",
+ "OMF",
+ "Out of Memory",
+ "Too Many Devices",
+ "Memory Buffer Mark Failure"
+};
+
+// ----------------------------------------------------------------------------
+// GLOBAL: EISA Checkpoint matrix
+// ----------------------------------------------------------------------------
+//
+// 1 2 3 4 5 6 7
+// 1234567890123456789012345678901234567890123456789012345678901234567890
+
+
+EISA_CHECKPOINT_INFO EisaCheckpointInfo[] = {
+ // Descriptions Flags Par SubPar Led SubLed
+
+ { "Interrupt Controller (PIC)", 0x08, 0x20, 0x00, 0xE, 0x00 },
+ { "Direct Memory Access (DMA)", 0x08, 0x21, 0x00, 0xE, 0x01 },
+ { "Non Maskable Interrupt (NMI)", 0x0A, 0x22, 0x00, 0xE, 0x02 },
+ { "Memory Refresh", 0x08, 0x23, 0x00, 0xE, 0x03 },
+ { "System Control Port B", 0x08, 0x24, 0x00, 0xE, 0x04 },
+ { "Timer 1", 0x08, 0x25, 0x00, 0xE, 0x05 },
+ { "Timer 2", 0x08, 0x26, 0x00, 0xE, 0x06 },
+ { NULL, 0x04, 0x27, 0x00, 0xE, 0x07 },
+ { NULL, 0x02, 0x30, 0x00, 0xF, 0x00 }
+};
+
+PCHAR EISA_INIT_MSG = " EISA Bus %lu Initialization in progress...";
+PCHAR EISA_BUS_MSG = "EISA Bus";
+PCHAR EISA_ERROR_SLOT_MSG = "\r\n Slot(%lu) %s";
+PCHAR EISA_HOT_NMI_MSG = "Hot NMI Detected\n\r";
+PCHAR EISA_BUS_NUMBER_MSG = "\n\rEISA Bus %lu : ";
+PCHAR EISA_NMI_NOT_FOUND_MSG = "NMI not found\n\r";
+PCHAR EISA_PARITY_ERROR_MSG = "\r%c16CParity Error\r\n";
+PCHAR EISA_IO_CHECK_ERROR_MSG = "\r%c16CI/O Check Error";
+PCHAR EISA_IO_CHECK_NOT_SUP_MSG = ", IOCHKERR not supported\n\r";
+PCHAR EISA_IN_SLOT_MSG = " in Slot %lu\n\r";
+PCHAR EISA_BUS_MASTER_MSG = "\r%c16CBus Master ";
+PCHAR EISA_TIMEOUT_MSG = "%lu Timeout\n\r";
+PCHAR EISA_TIMEOUT2_MSG = "? Timeout\n\r";
+PCHAR EISA_SLAVE_TIMEOUT_MSG = "\r%c16CSlave Timeout\n\r";
+PCHAR EISA_CANT_MARK_BUFFER_MSG = "? ERROR: Cannot mark buffer, Status = 0x%x.\r\n";
+PCHAR EISA_BAD_INDEX_MSG = "? ERROR: Index = 0x%x, which is greater than 0x%x.\r\n";
diff --git a/private/ntos/fw/alpha/fakebldr.c b/private/ntos/fw/alpha/fakebldr.c
new file mode 100644
index 000000000..38153d82e
--- /dev/null
+++ b/private/ntos/fw/alpha/fakebldr.c
@@ -0,0 +1,165 @@
+#include "fwp.h"
+#include "jnsnvdeo.h"
+#include "jnvendor.h"
+
+VOID
+main(
+ int argc,
+ char *argv[],
+ char *envp[]
+ )
+{
+ ULONG Index;
+ UCHAR Character;
+ ULONG Count;
+ LONG DefaultChoice = 0;
+ PCHAR Choices[] = {
+ "Print out argc",
+ "Print out argv list",
+ "Print out envp list",
+ "Exit"
+ };
+#define NUMBER_OF_CHOICES (sizeof(Choices) / sizeof(ULONG))
+
+
+ while (TRUE) {
+
+ VenSetScreenAttributes( TRUE, FALSE, FALSE);
+ VenPrint1("%c2J", ASCII_CSI);
+ VenSetPosition( 0, 0);
+ VenPrint("Welcome to the Alpha fake osloader!!\r\n");
+
+ for (Index = 0; Index < NUMBER_OF_CHOICES ; Index++ ) {
+ VenSetPosition( Index + 2, 5);
+ if (Index == DefaultChoice) {
+ VenSetScreenAttributes( TRUE, FALSE, TRUE);
+ VenPrint(Choices[Index]);
+ VenSetScreenAttributes( TRUE, FALSE, FALSE);
+ } else {
+ VenPrint(Choices[Index]);
+ }
+ }
+
+ VenSetPosition(NUMBER_OF_CHOICES + 2, 0);
+
+ Character = 0;
+ do {
+ if (ArcGetReadStatus(ARC_CONSOLE_INPUT) == ESUCCESS) {
+ ArcRead(ARC_CONSOLE_INPUT, &Character, 1, &Count);
+ switch (Character) {
+
+ case ASCII_ESC:
+ ArcRead(ARC_CONSOLE_INPUT, &Character, 1, &Count);
+ if (Character != '[') {
+ break;
+ }
+
+ case ASCII_CSI:
+ ArcRead(ARC_CONSOLE_INPUT, &Character, 1, &Count);
+ VenSetPosition( DefaultChoice + 2, 5);
+ VenPrint(Choices[DefaultChoice]);
+ switch (Character) {
+ case 'A':
+ case 'D':
+ DefaultChoice--;
+ if (DefaultChoice < 0) {
+ DefaultChoice = NUMBER_OF_CHOICES-1;
+ }
+ break;
+ case 'B':
+ case 'C':
+ DefaultChoice++;
+ if (DefaultChoice == NUMBER_OF_CHOICES) {
+ DefaultChoice = 0;
+ }
+ break;
+ case 'H':
+ DefaultChoice = 0;
+ break;
+ default:
+ break;
+ }
+ VenSetPosition( DefaultChoice + 2, 5);
+ VenSetScreenAttributes( TRUE, FALSE, TRUE);
+ VenPrint(Choices[DefaultChoice]);
+ VenSetScreenAttributes( TRUE, FALSE, FALSE);
+ continue;
+
+ default:
+ break;
+ }
+ }
+
+ } while ((Character != '\n') && (Character != '\r'));
+
+ switch (DefaultChoice) {
+
+ //
+ // Print out argc
+ //
+
+ case 0:
+
+ VenSetPosition( 3, 5);
+ VenPrint("\x9BJ");
+ VenPrint1("argc is %x (hex).\r\n", argc);
+
+ VenPrint(" Press any key to continue...");
+ ArcRead(ARC_CONSOLE_INPUT, &Character, 1, &Count);
+ break;
+
+
+ //
+ // Print out argv list
+ //
+
+ case 1:
+
+ VenSetPosition( 3, 5);
+ VenPrint("\x9BJ");
+ VenPrint("argv list is...\r\n\n");
+
+ for (Index = 0; Index < argc; Index++) {
+ VenPrint2("argv[%d]=%s\r\n",
+ Index,
+ argv[Index]
+ );
+ }
+
+ VenPrint("\r\n Press any key to continue...");
+ ArcRead(ARC_CONSOLE_INPUT, &Character, 1, &Count);
+ break;
+
+
+ //
+ // Print out envp list
+ //
+
+ case 2:
+
+ VenSetPosition( 3, 5);
+ VenPrint("\x9BJ");
+ VenPrint("envp list is...\r\n\n");
+
+ Index = 0;
+ while (envp[Index] != NULL) {
+ VenPrint2("envp[%d]=%s\r\n", Index, envp[Index]);
+ Index++;
+ }
+ VenPrint1("envp[%d]=NULL\r\n", Index);
+
+ VenPrint("\r\n Press any key to continue...");
+ ArcRead(ARC_CONSOLE_INPUT, &Character, 1, &Count);
+ break;
+
+
+
+
+ default:
+ case 3:
+ return;
+
+ }
+
+ }
+}
diff --git a/private/ntos/fw/alpha/fakebldr.rsp b/private/ntos/fw/alpha/fakebldr.rsp
new file mode 100644
index 000000000..afc4db8fb
--- /dev/null
+++ b/private/ntos/fw/alpha/fakebldr.rsp
@@ -0,0 +1,10 @@
+-machine:alpha
+-fixed
+-rom
+-base:0x80600000
+-align:0x100
+-debug:none
+-debugtype:coff
+-entry:main
+obj\alpha\fakebldr.obj
+\nt\public\sdk\lib\alpha\libcnt.lib
diff --git a/private/ntos/fw/alpha/fwcallbk.h b/private/ntos/fw/alpha/fwcallbk.h
new file mode 100644
index 000000000..04fd1e490
--- /dev/null
+++ b/private/ntos/fw/alpha/fwcallbk.h
@@ -0,0 +1,279 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ fwcallbk.h
+
+Abstract:
+
+ This module defines the firmware vendor vector callbacks that
+ will be implemented on all Alpha AXP platforms.
+
+Author:
+
+ John DeRosa [DEC] 10-December-1993
+
+Revision History:
+
+--*/
+
+#ifndef _FWCALLBK_
+#define _FWCALLBK_
+
+//
+// This module contains typedefs, which are not parsable by the assembler.
+//
+
+#ifndef _LANGUAGE_ASSEMBLY
+
+#include "arc.h"
+
+//
+// Structure used to return system and processor information.
+//
+
+typedef struct _EXTENDED_SYSTEM_INFORMATION {
+ ULONG ProcessorId;
+ ULONG ProcessorRevision;
+ ULONG ProcessorPageSize;
+ ULONG NumberOfPhysicalAddressBits;
+ ULONG MaximumAddressSpaceNumber;
+ ULONG ProcessorCycleCounterPeriod;
+ ULONG SystemRevision;
+ UCHAR SystemSerialNumber[16];
+ UCHAR FirmwareVersion[16];
+ UCHAR FirmwareBuildTimeStamp[12];
+} EXTENDED_SYSTEM_INFORMATION, *PEXTENDED_SYSTEM_INFORMATION;
+
+//
+// Define structure used to call BIOS emulator. This mimics the
+// VIDEO_X86_BIOS_ARGUMENTS typedef in \nt\private\ntos\inc\video.h.
+//
+
+typedef struct X86_BIOS_ARGUMENTS {
+ ULONG Eax;
+ ULONG Ebx;
+ ULONG Ecx;
+ ULONG Edx;
+ ULONG Esi;
+ ULONG Edi;
+ ULONG Ebp;
+} X86_BIOS_ARGUMENTS, *PX86_BIOS_ARGUMENTS;
+
+//
+// Define the firmware vendor specific entry point numbers that are
+// common to all Alpha AXP platforms.
+//
+
+typedef enum _VENDOR_GENERIC_ENTRY {
+ AllocatePoolRoutine,
+ StallExecutionRoutine,
+ PrintRoutine,
+ ReturnExtendedSystemInformationRoutine,
+ VideoDisplayInitializeRoutine,
+ EISAReadRegisterBufferUCHARRoutine,
+ EISAWriteRegisterBufferUCHARRoutine,
+ EISAReadPortUCHARRoutine,
+ EISAReadPortUSHORTRoutine,
+ EISAReadPortULONGRoutine,
+ EISAWritePortUCHARRoutine,
+ EISAWritePortUSHORTRoutine,
+ EISAWritePortULONGRoutine,
+ FreePoolRoutine,
+ CallBiosRoutine,
+ MaximumVendorRoutine
+ } VENDOR_GENERIC_ENTRY;
+
+//
+// Define vendor specific routine types.
+//
+
+typedef
+PVOID
+(*PVEN_ALLOCATE_POOL_ROUTINE) (
+ IN ULONG NumberOfBytes
+ );
+
+typedef
+VOID
+(*PVEN_STALL_EXECUTION_ROUTINE) (
+ IN ULONG Microseconds
+ );
+
+typedef
+ULONG
+(*PVEN_PRINT_ROUTINE) (
+ IN PCHAR Format,
+ ...
+ );
+
+typedef
+VOID
+(*PVEN_RETURN_EXTENDED_SYSTEM_INFORMATION_ROUTINE) (
+ OUT PEXTENDED_SYSTEM_INFORMATION SystemInfo
+ );
+
+typedef
+ARC_STATUS
+(*PVEN_VIDEO_DISPLAY_INITIALIZE_ROUTINE) (
+ OUT PVOID UnusedParameter
+ );
+
+typedef
+ULONG
+(*PVEN_EISA_READ_REGISTER_BUFFER_UCHAR_ROUTINE) (
+ IN ULONG BusNumber,
+ IN ULONG Offset,
+ OUT PVOID Buffer,
+ IN ULONG Length
+ );
+
+typedef
+ULONG
+(*PVEN_EISA_WRITE_REGISTER_BUFFER_UCHAR_ROUTINE) (
+ IN ULONG BusNumber,
+ IN ULONG Offset,
+ OUT PVOID Buffer,
+ IN ULONG Length
+ );
+
+typedef
+UCHAR
+(*PVEN_EISA_READ_PORT_UCHAR_ROUTINE) (
+ IN ULONG BusNumber,
+ IN ULONG Offset
+ );
+
+typedef
+USHORT
+(*PVEN_EISA_READ_PORT_USHORT_ROUTINE) (
+ IN ULONG BusNumber,
+ IN ULONG Offset
+ );
+
+typedef
+ULONG
+(*PVEN_EISA_READ_PORT_ULONG_ROUTINE) (
+ IN ULONG BusNumber,
+ IN ULONG Offset
+ );
+
+typedef
+VOID
+(*PVEN_EISA_WRITE_PORT_UCHAR_ROUTINE) (
+ IN ULONG BusNumber,
+ IN ULONG Offset,
+ IN UCHAR Datum
+ );
+
+typedef
+VOID
+(*PVEN_EISA_WRITE_PORT_USHORT_ROUTINE) (
+ IN ULONG BusNumber,
+ IN ULONG Offset,
+ IN USHORT Datum
+ );
+
+typedef
+VOID
+(*PVEN_EISA_WRITE_PORT_ULONG_ROUTINE) (
+ IN ULONG BusNumber,
+ IN ULONG Offset,
+ IN ULONG Datum
+ );
+
+typedef
+VOID
+(*PVEN_FREE_POOL_ROUTINE) (
+ IN PVOID MemoryPointer
+ );
+
+typedef
+VOID
+(*PVEN_CALL_BIOS_ROUTINE) (
+ IN ULONG InterruptNumber,
+ IN OUT PX86_BIOS_ARGUMENTS BiosArguments
+ );
+
+
+//
+// Define vendor specific macros for use by programs that run on
+// Alpha AXP ARC firmware.
+//
+// These calls are guaranteed to return legitimate values. If a function
+// is not defined for a particular platform, it will return with an error
+// code or just return normally, as appropriate.
+//
+
+#define VenAllocatePool(NumberOfBytes) \
+ ((PVEN_ALLOCATE_MEMORY_ROUTINE)(SYSTEM_BLOCK->VendorVector[AllocatePoolRoutine])) \
+ ((NumberOfBytes))
+
+#define VenStallExecution(Microseconds) \
+ ((PVEN_STALL_EXECUTION_ROUTINE)(SYSTEM_BLOCK->VendorVector[StallExecutionRoutine])) \
+ ((Microseconds))
+
+#define VenPrint(x) \
+ ((PVEN_PRINT_ROUTINE)(SYSTEM_BLOCK->VendorVector[PrintRoutine])) \
+ ((x))
+
+#define VenPrint1(x,y) \
+ ((PVEN_PRINT_ROUTINE)(SYSTEM_BLOCK->VendorVector[PrintRoutine])) \
+ ((x), (y))
+
+#define VenPrint2(x,y,z) \
+ ((PVEN_PRINT_ROUTINE)(SYSTEM_BLOCK->VendorVector[PrintRoutine])) \
+ ((x), (y), (z))
+
+#define VenReturnExtendedSystemInformation(x) \
+ ((PVEN_RETURN_EXTENDED_SYSTEM_INFORMATION_ROUTINE)(SYSTEM_BLOCK->VendorVector[ReturnExtendedSystemInformationRoutine]))(x)
+
+#define VenVideoDisplayInitialize(x) \
+ ((PVEN_VIDEO_DISPLAY_INITIALIZE_ROUTINE)(SYSTEM_BLOCK->VendorVector[VideoDisplayInitializeRoutine]))(x)
+
+#define VenEISAReadRegisterBufferUCHAR(BusNumber, Offset, Buffer, Length) \
+ ((PVEN_EISA_READ_REGISTER_BUFFER_UCHAR_ROUTINE)(SYSTEM_BLOCK->VendorVector[EISAReadRegisterBufferUCHARRoutine])) \
+ ((BusNumber), (Offset), (Buffer), (Length))
+
+#define VenEISAWriteRegisterBufferUCHAR(BusNumber, Offset, Buffer, Length) \
+ ((PVEN_EISA_WRITE_REGISTER_BUFFER_UCHAR_ROUTINE)(SYSTEM_BLOCK->VendorVector[EISAWriteRegisterBufferUCHARRoutine])) \
+ ((BusNumber), (Offset), (Buffer), (Length))
+
+#define VenEISAReadPortUCHAR(BusNumber, Offset) \
+ ((PVEN_EISA_READ_PORT_UCHAR_ROUTINE)(SYSTEM_BLOCK->VendorVector[EISAReadPortUCHARRoutine])) \
+ ((BusNumber), (Offset))
+
+#define VenEISAReadPortUSHORT(BusNumber, Offset) \
+ ((PVEN_EISA_READ_PORT_USHORT_ROUTINE)(SYSTEM_BLOCK->VendorVector[EISAReadPortUSHORTRoutine])) \
+ ((BusNumber), (Offset))
+
+#define VenEISAReadPortULONG(BusNumber, Offset) \
+ ((PVEN_EISA_READ_PORT_ULONG_ROUTINE)(SYSTEM_BLOCK->VendorVector[EISAReadPortULONGRoutine])) \
+ ((BusNumber), (Offset))
+
+#define VenEISAWritePortUCHAR(BusNumber, Offset, Datum) \
+ ((PVEN_EISA_WRITE_PORT_UCHAR_ROUTINE)(SYSTEM_BLOCK->VendorVector[EISAWritePortUCHARRoutine])) \
+ ((BusNumber), (Offset), (Datum))
+
+#define VenEISAWritePortUSHORT(BusNumber, Offset, Datum) \
+ ((PVEN_EISA_WRITE_PORT_USHORT_ROUTINE)(SYSTEM_BLOCK->VendorVector[EISAWritePortUSHORTRoutine])) \
+ ((BusNumber), (Offset), (Datum))
+
+#define VenEISAWritePortULONG(BusNumber, Offset, Datum) \
+ ((PVEN_EISA_WRITE_PORT_ULONG_ROUTINE)(SYSTEM_BLOCK->VendorVector[EISAWritePortULONGRoutine])) \
+ ((BusNumber), (Offset), (Datum))
+
+#define VenFreePool(MemoryPointer) \
+ ((PVEN_FREE_POOL_ROUTINE)(SYSTEM_BLOCK->VendorVector[FreePoolRoutine])) \
+ ((MemoryPointer))
+
+#define VenCallBios(InterruptNumber, BiosArguments) \
+ ((PVEN_CALL_BIOS_ROUTINE)(SYSTEM_BLOCK->VendorVector[CallBiosRoutine])) \
+ ((InterruptNumber), (BiosArguments))
+
+
+#endif // _LANGUAGE_ASSEMBLY not defined
+
+#endif // _FWCALLBK_
diff --git a/private/ntos/fw/alpha/fwchkstk.s b/private/ntos/fw/alpha/fwchkstk.s
new file mode 100644
index 000000000..88343dc5a
--- /dev/null
+++ b/private/ntos/fw/alpha/fwchkstk.s
@@ -0,0 +1,136 @@
+// TITLE("Firmware Runtime Stack Checking")
+//++
+//
+// Copyright (c) 1993 Digital Equipment Corporation
+//
+// Module Name:
+//
+// fwchkstk.s
+//
+// Abstract:
+//
+// This module implements runtime stack checking for the Alpha AXP
+// NT firmware.
+//
+// Original comments are from David Cutler of Microsoft and Thomas
+// VanBaak of Digital.
+//
+// Author:
+//
+// John DeRosa [DEC] 26-January-1993
+//
+// Environment:
+//
+// Any mode.
+//
+// Revision History:
+//
+//
+//--
+
+#include "ksalpha.h"
+#include "fwmemdef.h"
+
+//
+// Static data
+//
+
+.align 4
+
+FwRtlStackLowerBound:
+.long FW_STACK_LOWER_BOUND
+
+ SBTTL("Check Stack")
+//++
+//
+// ULONG
+// _RtlCheckStack (
+// IN ULONG Allocation
+// )
+//
+// Routine Description:
+//
+// This function provides runtime stack checking for local allocations
+// within the executing environment of the NT Firmware. On Alpha AXP,
+// the firmware runs in superpage mode (physical = virtual). The requested
+// stack allocation is compared against the stack low limit, and if it
+// would exceed the stack then an error message is printed on the screen.
+//
+// The call to the FwPrint function for the error message will wind up
+// using stack space. This is accomplished by using a global variable
+// (FwRtlStackPanic) to indicate that _RtlCheckStack should just
+// return. Also, the 64KB underneath the Firmware stack is unused by
+// the Firmware, and will be used by the FwPrint functions to output
+// the error message.
+//
+// N.B. This routine is called using a non-standard calling sequence since
+// it is typically called from within the prologue. The allocation size
+// argument is in register t12 and it must be preserved. Register t11
+// may contain the callers saved ra and it must be preserved. The choice
+// of these registers is hard-coded into the acc C compiler. Register v0
+// may contain a static link pointer (exception handlers) and so it must
+// be preserved. Since this function is called from within the prolog,
+// the a' registers must be preserved, as well as all the s' registers.
+// Registers t8, t9, and t10 are used by this function and are not
+// preserved.
+//
+// The typical calling sequence from the prologue is:
+//
+// mov ra, t11 // save return address
+// ldil t12, SIZE // set requested stack frame size
+// bsr ra, _RtlCheckStack // check stack page allocation
+// subq sp, t12, sp // allocate stack frame
+// mov t11, ra // restore return address
+//
+// Arguments:
+//
+// Allocation (t12) - Supplies the size of the allocation on the stack.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(_RtlCheckStack)
+
+ ldl t8, FwRtlStackPanic // do we already have a bad stack?
+ bne t8, 40f // branch if t8<>0, = yes a bad stack.
+
+ subq sp, t12, t8 // compute requested new stack address
+ ldl t9, FwRtlStackLowerBound // get low limit of stack address
+
+//
+// The requested bottom of the stack is in t8.
+// The current low limit of the stack is in t9.
+//
+// If the new stack address is greater than the current stack limit then
+// the stack is good and nothing further needs to be done.
+//
+
+ cmpult t8, t9, t10 // t8<t9? new stack base within limit?
+ beq t10, 40f // if eq [false], then t8>=t9, so yes
+
+
+//
+// The requested lower stack address is below the bottom of the legal stack.
+//
+ ldl t8, 0x1
+ stl t8, FwRtlStackPanic
+
+//
+// The 64KB below the bottom of the stack is unused, so it is available
+// as a panic stack. The rest of the work is done in C, and there is no
+// reason to save the s0--s5 registers.
+//
+
+ mov t12, a2 # the requested stack allocation
+ mov t11, a1 # the caller of the caller
+ mov ra, a0 # the caller of _RtlCheckStack
+ jsr ra, FwErrorStackUnderflow # go do the work.
+
+10: br zero, 10b # it should never have returned.
+
+40: ret zero, (ra) // return
+
+ .end _RtlCheckStack
diff --git a/private/ntos/fw/alpha/fwhalt.c b/private/ntos/fw/alpha/fwhalt.c
new file mode 100644
index 000000000..853df392e
--- /dev/null
+++ b/private/ntos/fw/alpha/fwhalt.c
@@ -0,0 +1,441 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ fwhalt.c
+
+Abstract:
+
+
+ This module implements routines to process halts from the operating
+ system.
+
+Author:
+
+ Joe Notarangelo 24-Feb-1993
+
+Environment:
+
+ Firmware in Kernel mode only.
+
+Revision History:
+
+--*/
+
+
+#include "fwp.h"
+#include "fwpexcpt.h"
+#include "axp21064.h"
+#include "fwstring.h"
+
+//
+// Maximum size of Machine Check output string.
+//
+
+#define MAX_ERROR_STRING 100
+
+//
+// Function prototypes
+//
+
+VOID
+FwDisplayMchk(
+ IN PLOGOUT_FRAME_21064 LogoutFrame,
+ IN ULONG HaltReason
+ );
+
+VOID
+FwHaltToMonitor(
+ IN PALPHA_RESTART_SAVE_AREA AlphaSaveArea,
+ IN ULONG Reason
+ );
+
+VOID
+FwHalt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function receives control on a halt from the operating
+ system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PRESTART_BLOCK RestartBlock;
+ PALPHA_RESTART_SAVE_AREA AlphaSaveArea;
+ ALPHA_VIDEO_TYPE VideoType;
+ UCHAR Character;
+ ULONG Count;
+
+ //
+ // N.B. we will continue running on the stack re-established by
+ // the operating system for us.
+ //
+
+ //
+ // Reset the video state. If video init fails, continue as we may
+ // be directing output to the serial port.
+ //
+
+ DisplayBootInitialize(&VideoType);
+
+
+ //
+ // Verify the restart block.
+ //
+
+ if (FwVerifyRestartBlock() == FALSE) {
+ FwPrint (FW_INVALID_RESTART_BLOCK_MSG); // temp message
+ FwStallExecution(2 * 1000 * 1000);
+ //FwRestart(); // this will be real one day
+ }
+
+ //
+ // Dispatch on the halt reason code in the restart block.
+ //
+
+// AlphaSaveArea = (PALPHA_RESTART_SAVE_AREA)
+// &SYSTEM_BLOCK->RestartBlock->SaveArea;
+ AlphaSaveArea = (PALPHA_RESTART_SAVE_AREA)
+ &SYSTEM_BLOCK->RestartBlock->u.SaveArea;
+
+ switch (AlphaSaveArea->HaltReason) {
+
+
+ case AXP_HALT_REASON_HALT:
+
+ //
+ // Dispatch to monitor so that Joe can find his bug.
+ //
+
+ FwHaltToMonitor(AlphaSaveArea, FW_EXC_HALT);
+
+ //
+ // If we return then it is time to restart to get a real stack.
+ //
+
+ FwRestart();
+
+
+ case AXP_HALT_REASON_DBLMCHK:
+ case AXP_HALT_REASON_PALMCHK:
+
+ //
+ // Machine Check.
+ //
+
+ FwDisplayMchk(AlphaSaveArea->LogoutFrame, AlphaSaveArea->HaltReason);
+
+ //
+ // Find out what the user wants to do next. We will give her
+ // 2 choices: 1. enter monitor 2. restart
+ //
+
+ FwPrint(FW_SYSRQ_MONITOR_MSG);
+ FwRead(ARC_CONSOLE_INPUT, &Character, 1, &Count);
+
+ if (Character == ASCII_SYSRQ) {
+ FwHaltToMonitor(AlphaSaveArea, FW_EXC_MCHK);
+ }
+
+ //
+ // Restart the firmware when we return.
+ //
+
+ FwRestart();
+
+
+ case AXP_HALT_REASON_REBOOT:
+
+ FwReboot();
+
+
+ case AXP_HALT_REASON_RESTART:
+ default:
+
+ FwRestart();
+
+ }
+
+}
+
+
+VOID
+FwDisplayMchk(
+ IN PLOGOUT_FRAME_21064 LogoutFrame,
+ IN ULONG HaltReason
+ )
+/*++
+
+Routine Description:
+
+ This function displays the logout frame for a 21064.
+
+Arguments:
+
+ LogoutFrame - Supplies a pointer to the logout frame.
+ HaltReason - Supplies the reason for the halt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR OutBuffer[ MAX_ERROR_STRING ];
+
+
+ //
+ // PRINT_LOGOUT_VERBOSE controls the amount of text displayed
+ // of the logout frame. The macro can be undefined to save code and
+ // initialized data space in the rom. If the space exists it would be
+ // preferable to give the entire print out.
+ //
+
+#define PRINT_LOGOUT_VERBOSE 1
+
+
+ switch (HaltReason) {
+
+ case AXP_HALT_REASON_DBLMCHK:
+
+ FwPrint(FW_FATAL_DMC_MSG);
+ break;
+
+ case AXP_HALT_REASON_PALMCHK:
+
+ FwPrint(FW_FATAL_MCINPALMODE_MSG);
+ break;
+
+ default:
+
+ FwPrint(FW_FATAL_UNKNOWN_MSG);
+ }
+
+
+#ifdef PRINT_LOGOUT_VERBOSE
+
+ FwPrint("BIU_STAT : %16Lx BIU_ADDR: %16Lx\r\n",
+ BIUSTAT_ALL_21064(LogoutFrame->BiuStat),
+ LogoutFrame->BiuAddr.QuadPart);
+
+ FwPrint("FILL_ADDR: %16Lx FILL_SYN: %16Lx\r\n",
+ LogoutFrame->FillAddr.QuadPart,
+ FILLSYNDROME_ALL_21064(LogoutFrame->FillSyndrome) );
+
+ FwPrint("DC_STAT : %16Lx BC_TAG : %16Lx\r\n",
+ DCSTAT_ALL_21064(LogoutFrame->DcStat),
+ BCTAG_ALL_21064(LogoutFrame->BcTag) );
+
+ FwPrint("ICCSR : %16Lx ABOX_CTL: %16Lx EXC_SUM: %16Lx\r\n",
+ ICCSR_ALL_21064(LogoutFrame->Iccsr),
+ ABOXCTL_ALL_21064(LogoutFrame->AboxCtl),
+ EXCSUM_ALL_21064(LogoutFrame->ExcSum) );
+
+ FwPrint("EXC_ADDR : %16Lx VA : %16Lx MM_CSR : %16Lx\r\n",
+ LogoutFrame->ExcAddr.QuadPart,
+ LogoutFrame->Va.QuadPart,
+ MMCSR_ALL_21064(LogoutFrame->MmCsr) );
+
+ FwPrint("HIRR : %16Lx HIER : %16Lx PS : %16Lx\r\n",
+ IRR_ALL_21064(LogoutFrame->Hirr),
+ IER_ALL_21064(LogoutFrame->Hier),
+ PS_ALL_21064(LogoutFrame->Ps) );
+
+ FwPrint("PAL_BASE: %16Lx\r\n",
+ LogoutFrame->PalBase.QuadPart);
+
+#endif //PRINT_LOGOUT_VERBOSE
+
+
+ //
+ // Print out interpretation of the error.
+ //
+
+ //
+ // Check for tag control parity error.
+ //
+
+ if (BIUSTAT_TCPERR_21064(LogoutFrame->BiuStat) == 1) {
+
+ FwPrint(FW_FATAL_TAGCNTRL_PE_MSG,
+ BCTAG_TAGCTLP_21064(LogoutFrame->BcTag),
+ BCTAG_TAGCTLD_21064(LogoutFrame->BcTag),
+ BCTAG_TAGCTLS_21064(LogoutFrame->BcTag),
+ BCTAG_TAGCTLV_21064(LogoutFrame->BcTag) );
+ }
+
+ //
+ // Check for tag parity error.
+ //
+
+ if (BIUSTAT_TPERR_21064(LogoutFrame->BiuStat) == 1) {
+
+ FwPrint(FW_FATAL_TAG_PE_MSG,
+ BCTAG_TAG_21064(LogoutFrame->BcTag),
+ BCTAG_TAG_21064(LogoutFrame->BcTag) );
+ }
+
+ //
+ // Check for hard error.
+ //
+
+ if (BIUSTAT_HERR_21064(LogoutFrame->BiuStat) == 1) {
+
+ FwPrint(FW_FATAL_HEACK_MSG,
+ BIUSTAT_CMD_21064(LogoutFrame->BiuStat),
+ LogoutFrame->BiuAddr.QuadPart);
+ }
+
+ //
+ // Check for soft error.
+ //
+
+ if( BIUSTAT_SERR_21064(LogoutFrame->BiuStat) == 1 ){
+
+ FwPrint(FW_FATAL_SEACK_MSG,
+ BIUSTAT_CMD_21064(LogoutFrame->BiuStat),
+ LogoutFrame->BiuAddr.QuadPart);
+ }
+
+
+ //
+ // Check for fill ECC errors.
+ //
+
+ if( BIUSTAT_FILLECC_21064(LogoutFrame->BiuStat) == 1 ){
+
+ FwPrint(FW_FATAL_ECC_ERROR_MSG,
+ (BIUSTAT_FILLIRD_21064(LogoutFrame->BiuStat) ?
+ "Icache Fill" : "Dcache Fill") );
+
+ FwPrint(FW_FATAL_QWLWLW_MSG,
+ LogoutFrame->FillAddr.QuadPart,
+ BIUSTAT_FILLQW_21064(LogoutFrame->BiuStat),
+ FILLSYNDROME_LO_21064(LogoutFrame->FillSyndrome),
+ FILLSYNDROME_HI_21064(LogoutFrame->FillSyndrome) );
+ }
+
+ //
+ // Check for fill Parity errors.
+ //
+
+ if( BIUSTAT_FILLDPERR_21064(LogoutFrame->BiuStat) == 1 ){
+
+ FwPrint(FW_FATAL_PE_MSG,
+ (BIUSTAT_FILLIRD_21064(LogoutFrame->BiuStat) ?
+ "Icache Fill" : "Dcache Fill") );
+
+ FwPrint(FW_FATAL_QWLWLW_MSG,
+ LogoutFrame->FillAddr.QuadPart,
+ BIUSTAT_FILLQW_21064(LogoutFrame->BiuStat),
+ FILLSYNDROME_LO_21064(LogoutFrame->FillSyndrome),
+ FILLSYNDROME_HI_21064(LogoutFrame->FillSyndrome) );
+ }
+
+ //
+ // Check for multiple hard errors.
+ //
+
+ if (BIUSTAT_FATAL1_21064(LogoutFrame->BiuStat) == 1) {
+ FwPrint(FW_FATAL_MULTIPLE_EXT_TAG_ERRORS_MSG);
+ }
+
+ //
+ // Check for multiple fill errors.
+ //
+
+ if (BIUSTAT_FATAL2_21064(LogoutFrame->BiuStat) == 1) {
+ FwPrint(FW_FATAL_MULTIPLE_FILL_ERRORS_MSG);
+ }
+
+
+ //
+ // return to caller
+ //
+
+ return;
+}
+
+VOID
+FwHaltToMonitor(
+ IN PALPHA_RESTART_SAVE_AREA AlphaSaveArea,
+ IN ULONG Reason
+ )
+/*++
+
+Routine Description:
+
+ This function transfers control to the firmware Monitor.
+
+Arguments:
+
+ AlphaSaveArea - Supplies a pointer to the Alpha save area portion
+ of the restart block.
+
+ Reason - The reason for going to the monitor.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PFW_EXCEPTION_FRAME ExceptionFrame;
+
+ //
+ // Allocate the exception frame.
+ //
+
+ ExceptionFrame = FwAllocatePool(sizeof(FW_EXCEPTION_FRAME));
+
+ //
+ // Copy the integer registers to the exception frame.
+ //
+
+ RtlMoveMemory(&ExceptionFrame->ExceptionV0, &AlphaSaveArea->IntV0,
+ 32 * 8);
+
+ //
+ // Copy the floating point registers to the exception frame.
+ //
+
+ RtlMoveMemory(&ExceptionFrame->ExceptionF0, &AlphaSaveArea->FltF0,
+ 32 * 8);
+
+ //
+ // Copy miscellaneous registers.
+ //
+
+ ExceptionFrame->ExceptionFaultingInstructionAddress =
+ (LONG)(AlphaSaveArea->ReiRestartAddress - 4);
+
+ ExceptionFrame->ExceptionProcessorStatus = AlphaSaveArea->Psr;
+
+ ExceptionFrame->ExceptionType = Reason;
+
+ ExceptionFrame->ExceptionParameter1 = (LONG)AlphaSaveArea;
+
+ //
+ // Dispatch to the monitor.
+ //
+
+ Monitor( 0, ExceptionFrame );
+
+ return;
+}
diff --git a/private/ntos/fw/alpha/fwio.c b/private/ntos/fw/alpha/fwio.c
new file mode 100644
index 000000000..d8fed7671
--- /dev/null
+++ b/private/ntos/fw/alpha/fwio.c
@@ -0,0 +1,1628 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ fwio.c
+
+Abstract:
+
+ This module implements the ARC firmware I/O operations for a MIPS
+ R3000 or R3000 Jazz system, or for the DEC Alpha/Jensen system.
+
+Author:
+
+ David N. Cutler (davec) 14-May-1991
+
+
+Revision History:
+
+ Lluis Abello (lluis) 20-Jun-1991
+
+ 15-April-1992 John DeRosa [DEC]
+
+ Added Alpha/Jensen hooks.
+
+--*/
+
+
+#include "fwp.h"
+#include "string.h"
+#include "fwstring.h"
+
+
+//
+// Needed to fix a bug in the bldr\scsiboot.c file where repeated reboots
+// would cause a crash due to walking off the end of an array.
+//
+
+ULONG ScsiPortCount;
+PDEVICE_OBJECT ScsiPortDeviceObject[10];
+
+//
+// Define file table.
+//
+
+BL_FILE_TABLE BlFileTable[BL_FILE_TABLE_SIZE];
+
+#define DEVICE_DEVICE 0xDEAD
+
+extern PADAPTER_OBJECT MasterAdapterObject;
+extern PADAPTER_OBJECT HalpEisaAdapter[8];
+
+#if !defined(FAILSAFE_BOOTER) && defined(EISA_PLATFORM)
+extern BL_DEVICE_ENTRY_TABLE OmfEntryTable;
+extern BL_DEVICE_ENTRY_TABLE OmfFileEntryTable;
+#endif
+
+//
+// Declare the table of opened devices.
+//
+OPENED_PATHNAME_ENTRY OpenedPathTable[SIZE_OF_OPENED_PATHNAME_TABLE];
+
+//
+// Declare the table of opened drivers.
+//
+DRIVER_LOOKUP_ENTRY DeviceLookupTable[SIZE_OF_LOOKUP_TABLE];
+
+//
+// Define data structure for the file system structure context.
+//
+
+typedef union _FILE_SYSTEM_STRUCTURE {
+ FAT_STRUCTURE_CONTEXT FatContext;
+ NTFS_STRUCTURE_CONTEXT NtfsContext;
+ ULONG Tmp;
+} FILE_SYSTEM_STRUCTURE, *PFILE_SYSTEM_STRUCTURE;
+
+typedef struct _FS_POOL_ENTRY {
+ BOOLEAN InUse;
+ FILE_SYSTEM_STRUCTURE Fs;
+} FS_POOL_ENTRY, *PFS_POOL_ENTRY;
+
+
+//
+// The pool size was reduced from eight to five as an easy way to include
+// NTFS booting without radically changing the manipulation of the firmware
+// file system pool.
+//
+//#define FS_POOL_SIZE 8
+//
+#define FS_POOL_SIZE 5
+
+PFS_POOL_ENTRY FileSystemStructurePool;
+
+//
+// Declare local procedures
+//
+
+VOID
+FiFreeFsStructure(
+ IN PFILE_SYSTEM_STRUCTURE PFs
+ );
+
+PVOID
+FiAllocateFsStructure(
+ VOID
+ );
+
+
+ARC_STATUS
+FiGetFileTableEntry(
+ OUT PULONG Entry
+ );
+
+PFAT_STRUCTURE_CONTEXT
+FiAllocateFatStructure(
+ VOID
+ );
+
+
+ARC_STATUS
+FwGetFileInformation (
+ IN ULONG FileId,
+ OUT PFILE_INFORMATION Finfo
+ )
+
+/*++
+
+Routine Description:
+
+ This function gets the file information for the specified FileId.
+
+Arguments:
+
+ FileId - Supplies the file table index.
+
+ Finfo - Supplies a pointer to where the File Informatino is stored.
+
+Return Value:
+
+ If the specified file is open then this routine dispatches to the
+ File routine.
+ Otherwise, returns an unsuccessful status.
+
+--*/
+
+{
+
+ if (BlFileTable[FileId].Flags.Open == 1) {
+ return (BlFileTable[FileId].DeviceEntryTable->GetFileInformation)(FileId,
+ Finfo);
+ } else {
+ return EACCES;
+ }
+}
+
+ARC_STATUS
+FwSetFileInformation (
+ IN ULONG FileId,
+ IN ULONG AttributeFlags,
+ IN ULONG AttributeMask
+ )
+
+/*++
+
+Routine Description:
+
+ This function sets the file attributes for the specified FileId.
+
+Arguments:
+
+ FileId - Supplies the file table index.
+
+ AttributeFlags - Supply the attributes to be set for the file.
+ AttributeMask
+
+Return Value:
+
+ If the specified file is open and is not a device then this routine
+ dispatches to the file system routine.
+ Otherwise, returns an unsuccessful status.
+
+--*/
+
+{
+
+ if ((BlFileTable[FileId].Flags.Open == 1) &&
+ (BlFileTable[FileId].DeviceId != DEVICE_DEVICE)) {
+ return (BlFileTable[FileId].DeviceEntryTable->SetFileInformation)(FileId,
+ AttributeFlags,
+ AttributeMask);
+ } else {
+ return EACCES;
+ }
+}
+
+
+ARC_STATUS
+FwMount (
+ IN PCHAR MountPath,
+ IN MOUNT_OPERATION Operation
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+
+ return ESUCCESS;
+}
+
+ARC_STATUS
+FwRead (
+ IN ULONG FileId,
+ OUT PVOID Buffer,
+ IN ULONG Length,
+ OUT PULONG Count
+ )
+
+/*++
+
+Routine Description:
+
+ This function reads from a file or a device that is open.
+
+ Alpha/Jensen cannot do DMA in the .5MB -- 1MB memory space, so
+ transfers within that space are done through another buffer. This is
+ transparent to the code that called this function. \TBD\: whether
+ other Alpha PC's need this fix too. We will leave the fix in for
+ now as Alpha-generic.
+
+Arguments:
+
+ FileId - Supplies the file table index.
+
+ Buffer - Supplies a pointer to the buffer that receives the data
+ read.
+
+ Length - Supplies the number of bytes that are to be read.
+
+ Count - Supplies a pointer to a variable that receives the number of
+ bytes actually transfered.
+
+Return Value:
+
+ If the specified file is open for read, then a read is attempted
+ and the status of the operation is returned. Otherwise, return an
+ unsuccessful status.
+
+--*/
+
+{
+#ifdef ALPHA
+
+ // These are for buffering DMA data destined for .5MB -- 1MB addresses.
+
+ ARC_STATUS Status;
+ UCHAR LocalSectorBuffer[SECTOR_SIZE];
+ PUCHAR LocalBuffer = Buffer;
+ ULONG LocalLengthRemaining = Length;
+ ULONG LocalCountSum = 0;
+ ULONG LocalLength;
+ ULONG LocalCount;
+ PUCHAR P_512KB;
+ PUCHAR P_1MB;
+
+#endif
+
+ //
+ // If the file is open for read, then attempt to read from it. Otherwise
+ // return an access error.
+ //
+
+ if ((BlFileTable[FileId].Flags.Open == 1) &&
+ (BlFileTable[FileId].Flags.Read == 1)) {
+
+#ifdef ALPHA
+
+ //
+ // These pointers are used to compare buffer addresses to the
+ // Alpha/Jensen missing memory DMA section of .5MB -- 1MB.
+ // The KSEG0_BASE bit is set if the incoming Buffer address has it
+ // set.
+ //
+
+ P_512KB = (PUCHAR)(_512_KB | ((ULONG)Buffer & KSEG0_BASE));
+ P_1MB = (PUCHAR)(ONE_MB | ((ULONG)Buffer & KSEG0_BASE));
+
+
+
+
+ //
+ // LocalBuffer and LocalLengthRemaining are bumped along by each
+ // section of the JENSEN code to simplify the comparisons.
+ //
+ // LocalCountSum will keep a running total of the bytes actually
+ // transferred. This is initialized to zero.
+ //
+
+
+ //
+ // Read the part below .5MB.
+ //
+
+ if (LocalBuffer < P_512KB) {
+
+ LocalLength = ((LocalBuffer + LocalLengthRemaining) > P_512KB) ?
+ (P_512KB - LocalBuffer) : LocalLengthRemaining;
+
+ Status = (BlFileTable[FileId].DeviceEntryTable->Read)(FileId,
+ LocalBuffer,
+ LocalLength,
+ &LocalCount);
+
+ LocalBuffer += LocalLength;
+ LocalLengthRemaining -= LocalLength;
+ LocalCountSum += LocalCount;
+
+
+ if (Status != ESUCCESS) {
+ *Count = LocalCountSum;
+ return (Status);
+ }
+
+ }
+
+
+ //
+ // Read the part between .5MB and 1MB.
+ //
+
+ if ((LocalBuffer >= P_512KB) &&
+ (LocalBuffer < P_1MB) &&
+ (LocalLengthRemaining > 0)) {
+
+ // Calculate amount to read
+
+ LocalLength = LocalLengthRemaining > _512_KB ?
+ _512_KB : LocalLengthRemaining;
+
+ //
+ // Now read the data into this region via LocalSectorBuffer.
+ //
+ // First read in data in chunks of SECTOR_SIZE size, and then
+ // read in any remaining bytes. Note: C integer division
+ // truncates any fractional part.
+ //
+
+ while (LocalLength / SECTOR_SIZE) {
+
+ Status = (BlFileTable[FileId].DeviceEntryTable->Read)(FileId,
+ LocalSectorBuffer,
+ SECTOR_SIZE,
+ &LocalCount);
+
+
+ RtlMoveMemory ( LocalBuffer, LocalSectorBuffer, SECTOR_SIZE );
+
+ LocalBuffer += SECTOR_SIZE;
+ LocalLengthRemaining -= SECTOR_SIZE;
+ LocalLength -= SECTOR_SIZE;
+ LocalCountSum += LocalCount;
+
+ if (Status != ESUCCESS) {
+ *Count = LocalCountSum;
+ return (Status);
+ }
+
+ }
+
+
+ //
+ // Now read in any remaining bytes.
+ //
+
+ if (LocalLength) {
+
+ Status = (BlFileTable[FileId].DeviceEntryTable->Read)(FileId,
+ LocalSectorBuffer,
+ LocalLength,
+ &LocalCount);
+
+
+ RtlMoveMemory ( LocalBuffer, LocalSectorBuffer, LocalLength );
+
+ LocalBuffer += LocalLength;
+ LocalLengthRemaining -= LocalLength;
+ LocalCountSum += LocalCount;
+
+ if (Status != ESUCCESS) {
+ *Count = LocalCountSum;
+ return (Status);
+ }
+
+ }
+
+ }
+
+
+
+ //
+ // Read the part above 1MB.
+ //
+
+
+ if ((LocalBuffer >= P_1MB) &&
+ (LocalLengthRemaining > 0)) {
+
+ Status = (BlFileTable[FileId].DeviceEntryTable->Read)(FileId,
+ LocalBuffer,
+ LocalLengthRemaining,
+ &LocalCount);
+
+
+ LocalCountSum += LocalCount;
+
+ }
+
+
+
+ //
+ // The read must have succeeded. Return Status and Count.
+ //
+ *Count = LocalCountSum;
+ return (ESUCCESS);
+
+#else
+ // Non-JENSEN code.
+
+ return (BlFileTable[FileId].DeviceEntryTable->Read)(FileId,
+ Buffer,
+ Length,
+ Count);
+#endif
+
+ } else {
+ return EACCES;
+ }
+}
+
+ARC_STATUS
+FwGetReadStatus (
+ IN ULONG FileId
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+
+ //
+ // If the file is open for read, then call the call the specific routine.
+ // Otherwise return an access error.
+
+ if ((BlFileTable[FileId].Flags.Open == 1) &&
+ (BlFileTable[FileId].Flags.Read == 1)) {
+
+ //
+ // Make sure there is a valid GetReadStatus entry.
+ //
+
+ if (BlFileTable[FileId].DeviceEntryTable->GetReadStatus != NULL) {
+ return(BlFileTable[FileId].DeviceEntryTable->GetReadStatus)(FileId);
+ } else {
+ return(EACCES);
+ }
+
+ } else {
+ return EACCES;
+ }
+
+ return ESUCCESS;
+}
+
+ARC_STATUS
+FwSeek (
+ IN ULONG FileId,
+ IN PLARGE_INTEGER Offset,
+ IN SEEK_MODE SeekMode
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+ If the specified file is open, then a seek is attempted and
+ the status of the operation is returned. Otherwise, return an
+ unsuccessful status.
+
+--*/
+
+{
+
+ //
+ // If the file is open, then attempt to seek on it. Otherwise return an
+ // access error.
+ //
+
+ if (BlFileTable[FileId].Flags.Open == 1) {
+ return (BlFileTable[FileId].DeviceEntryTable->Seek)(FileId,
+ Offset,
+ SeekMode);
+ } else {
+ return EACCES;
+ }
+}
+
+ARC_STATUS
+FwWrite (
+ IN ULONG FileId,
+ IN PVOID Buffer,
+ IN ULONG Length,
+ OUT PULONG Count
+ )
+
+/*++
+
+Routine Description:
+
+ This function writes to a file or a device that is open.
+
+ Alpha/Jensen cannot do DMA in the .5MB -- 1MB memory space, so
+ transfers within that space are done through another buffer. This is
+ transparent to the code that called this function.
+
+
+Arguments:
+
+ FileId - Supplies the file table index.
+
+ Buffer - Supplies a pointer to the buffer that contains the data
+ to write.
+
+ Length - Supplies the number of bytes that are to be written.
+
+ Count - Supplies a pointer to a variable that receives the number of
+ bytes actually transfered.
+
+Return Value:
+
+ If the specified file is open for write, then a write is attempted
+ and the status of the operation is returned. Otherwise, return an
+ unsuccessful status.
+
+--*/
+
+{
+#ifdef ALPHA
+
+ // These are for buffering DMA data from .5MB -- 1MB addresses.
+
+ ARC_STATUS Status;
+ UCHAR LocalSectorBuffer[SECTOR_SIZE];
+ PUCHAR LocalBuffer = Buffer;
+ ULONG LocalLengthRemaining = Length;
+ ULONG LocalCountSum = 0;
+ ULONG LocalLength;
+ ULONG LocalCount;
+ PUCHAR P_512KB;
+ PUCHAR P_1MB;
+
+#endif
+
+ //
+ // If the file is open for write, then attempt to write to it. Otherwise
+ // return an access error.
+ //
+
+ if ((BlFileTable[FileId].Flags.Open == 1) &&
+ (BlFileTable[FileId].Flags.Write == 1)) {
+
+#ifdef ALPHA
+
+ //
+ // These pointers are used to compare buffer addresses to the
+ // Alpha/Jensen missing memory DMA section of .5MB -- 1MB.
+ // The KSEG0_BASE bit is set if the incoming Buffer address has it
+ // set.
+ //
+
+ P_512KB = (PUCHAR)(_512_KB | ((ULONG)Buffer & KSEG0_BASE));
+ P_1MB = (PUCHAR)(ONE_MB | ((ULONG)Buffer & KSEG0_BASE));
+
+
+
+
+ //
+ // LocalBuffer and LocalLengthRemaining are bumped along by each
+ // section of the JENSEN code to simplify the comparisons.
+ //
+ // LocalCountSum will keep a running total of the bytes actually
+ // transferred. This is initialized to zero.
+ //
+
+
+ //
+ // Write the part below .5MB.
+ //
+
+ if (LocalBuffer < P_512KB) {
+
+ LocalLength = ((LocalBuffer + LocalLengthRemaining) > P_512KB) ?
+ (P_512KB - LocalBuffer) : LocalLengthRemaining;
+
+ Status = (BlFileTable[FileId].DeviceEntryTable->Write)(FileId,
+ LocalBuffer,
+ LocalLength,
+ &LocalCount);
+
+ LocalBuffer += LocalLength;
+ LocalLengthRemaining -= LocalLength;
+ LocalCountSum += LocalCount;
+
+
+ if (Status != ESUCCESS) {
+ *Count = LocalCountSum;
+ return (Status);
+ }
+
+ }
+
+
+ //
+ // Write the part between .5MB and 1MB.
+ //
+
+ if ((LocalBuffer >= P_512KB) &&
+ (LocalBuffer < P_1MB) &&
+ (LocalLengthRemaining > 0)) {
+
+ // Calculate amount to write
+
+ LocalLength = LocalLengthRemaining > _512_KB ?
+ _512_KB : LocalLengthRemaining;
+
+ //
+ // Now write the data into this region via LocalSectorBuffer.
+ //
+ // First write data in chunks of SECTOR_SIZE size, and then
+ // write any remaining bytes. Note: C integer division
+ // truncates any fractional part.
+ //
+
+ while (LocalLength / SECTOR_SIZE) {
+
+ RtlMoveMemory ( LocalSectorBuffer, LocalBuffer, SECTOR_SIZE );
+
+ Status = (BlFileTable[FileId].DeviceEntryTable->Write)(FileId,
+ LocalSectorBuffer,
+ SECTOR_SIZE,
+ &LocalCount);
+
+ LocalBuffer += SECTOR_SIZE;
+ LocalLengthRemaining -= SECTOR_SIZE;
+ LocalLength -= SECTOR_SIZE;
+ LocalCountSum += LocalCount;
+
+ if (Status != ESUCCESS) {
+ *Count = LocalCountSum;
+ return (Status);
+ }
+
+ }
+
+
+ //
+ // Now write any remaining bytes.
+ //
+
+ if (LocalLength) {
+
+ RtlMoveMemory ( LocalSectorBuffer, LocalBuffer, LocalLength );
+
+ Status = (BlFileTable[FileId].DeviceEntryTable->Write)(FileId,
+ LocalSectorBuffer,
+ LocalLength,
+ &LocalCount);
+
+
+ LocalBuffer += LocalLength;
+ LocalLengthRemaining -= LocalLength;
+ LocalCountSum += LocalCount;
+
+ if (Status != ESUCCESS) {
+ *Count = LocalCountSum;
+ return (Status);
+ }
+
+ }
+
+ }
+
+
+
+ //
+ // Write the part above 1MB.
+ //
+
+
+ if ((LocalBuffer >= P_1MB) &&
+ (LocalLengthRemaining > 0)) {
+
+ Status = (BlFileTable[FileId].DeviceEntryTable->Write)(FileId,
+ LocalBuffer,
+ LocalLengthRemaining,
+ &LocalCount);
+
+
+ LocalCountSum += LocalCount;
+
+ }
+
+
+
+ //
+ // The write must have succeeded. Return Status and Count.
+ //
+ *Count = LocalCountSum;
+ return (ESUCCESS);
+
+#else
+ // Non-JENSEN code.
+
+ return (BlFileTable[FileId].DeviceEntryTable->Write)(FileId,
+ Buffer,
+ Length,
+ Count);
+#endif
+
+ } else {
+ return EACCES;
+ }
+}
+
+ARC_STATUS
+FwGetDirectoryEntry (
+ IN ULONG FileId,
+ OUT PDIRECTORY_ENTRY Buffer,
+ IN ULONG Length,
+ OUT PULONG Count
+ )
+
+/*++
+
+Routine Description:
+
+ This function reads from a file the requested number of directory entries.
+
+Arguments:
+
+ FileId - Supplies the file table index.
+
+ Buffer - Supplies a pointer to the buffer to receive the directory
+ entries.
+
+ Length - Supplies the number of directory entries to be read.
+
+ Count - Supplies a pointer to a variable that receives the number of
+ directory entries actually read..
+
+Return Value:
+
+ If the specified file is open for read, then a read is attempted
+ and the status of the operation is returned. Otherwise, return an
+ unsuccessful status.
+
+--*/
+{
+ //
+ // If the file is open for read, then call the specific routine.
+ // Otherwise return an access error.
+ //
+
+ if ((FileId < BL_FILE_TABLE_SIZE) &&
+ (BlFileTable[FileId].Flags.Open == 1) &&
+ (BlFileTable[FileId].Flags.Read == 1) &&
+ (BlFileTable[FileId].DeviceId != DEVICE_DEVICE)) {
+
+ //
+ // Check to make sure a GetDirectoryEntry routine exists
+ //
+
+ if (BlFileTable[FileId].DeviceEntryTable->GetDirectoryEntry != NULL) {
+ return (BlFileTable[FileId].DeviceEntryTable->GetDirectoryEntry)
+ (FileId, Buffer, Length, Count);
+ }
+ } else {
+ return EBADF;
+ }
+}
+
+
+ARC_STATUS
+FwClose (
+ IN ULONG FileId
+ )
+
+/*++
+
+Routine Description:
+
+ This function closes a file or a device if it's open.
+ The DeviceId field indicates if the FileId is a device
+ (it has the value DEVICE_DEVICE) or is a file.
+ When closing a file, after the file is closed the
+ reference counter for the device is decremented and if zero
+ the device is also closed and the device name removed from
+ the table of opened devices.
+ If FileId specifies a device, the reference counter is
+ decremented and if zero the device is closed and the device
+ name removed from the table of opened devices.
+
+Arguments:
+
+ FileId - Supplies the file table index.
+
+Return Value:
+
+ If the specified file is open, then a close is attempted and
+ the status of the operation is returned. Otherwise, return an
+ unsuccessful status.
+
+--*/
+
+{
+ ULONG DeviceId;
+ ARC_STATUS Status;
+ if (BlFileTable[FileId].Flags.Open == 1) {
+ //
+ // Check if closing a file or a device
+ //
+ if (BlFileTable[FileId].DeviceId == DEVICE_DEVICE) {
+ //
+ // Decrement reference counter, if it's zero call the device
+ // close routine.
+ //
+ OpenedPathTable[FileId].ReferenceCounter--;
+ if (OpenedPathTable[FileId].ReferenceCounter == 0) {
+ //
+ // Remove the name of the device from the table of opened devices.
+ //
+ OpenedPathTable[FileId].DeviceName[0] = '\0';
+
+ //
+ // Call the device specific close routine.
+ //
+ Status = (BlFileTable[FileId].DeviceEntryTable->Close)(FileId);
+
+ //
+ // If the device has a file system, free the memory used for
+ // the STRUCTURE_CONTEXT.
+ //
+ if (BlFileTable[FileId].StructureContext != NULL) {
+ FiFreeFsStructure(BlFileTable[FileId].StructureContext);
+ }
+ return Status;
+ } else {
+ return ESUCCESS;
+ }
+ } else {
+ //
+ // Close the file
+ //
+ DeviceId= BlFileTable[FileId].DeviceId;
+ Status = (BlFileTable[FileId].DeviceEntryTable->Close)(FileId);
+ if (Status) {
+ return Status;
+ }
+
+ //
+ // Close also the device
+ //
+ return FwClose(DeviceId);
+ }
+ } else {
+ return EACCES;
+ }
+}
+
+ARC_STATUS
+FwOpen (
+ IN PCHAR OpenPath,
+ IN OPEN_MODE OpenMode,
+ OUT PULONG FileId
+ )
+
+/*++
+
+Routine Description:
+
+ This function opens the file specified by OpenPath.
+ If the device portion of the pathanme is already opened, it reuses
+ the fid. Otherwise it looks for a driver able to handle this
+ device and logs the opened device so that it can be reused.
+
+Arguments:
+
+ OpenPath - ARC compliant pathname of the device/file to be opened.
+ OpenMode - Supplies the mode in wich the file is opened.
+ FileId - Pointer to a variable that receives the fid for this
+ pathname.
+
+Return Value:
+
+ If the file is successfully opened returns ESUCCESS otherwise
+ returns an unsuccessfull status.
+
+--*/
+
+{
+ ULONG i;
+ ULONG DeviceId;
+ PCHAR FileName ;
+ PCHAR TempString1;
+ PCHAR TempString2;
+ ARC_STATUS Status;
+ CHAR DeviceName[80];
+ PVOID TmpStructureContext;
+ OPEN_MODE DeviceOpenMode;
+#if !defined(FAILSAFE_BOOTER) && defined(EISA_PLATFORM)
+ BOOLEAN OmfProtocol;
+#endif
+
+ //
+ // Split OpenPath into DeviceName and FileName.
+ // Search for the last ')'
+ //
+ FileName = OpenPath;
+ for (TempString1 = OpenPath; *TempString1; TempString1++) {
+ if ( *TempString1 == ')') {
+ FileName = TempString1+1;
+ }
+ }
+ if (FileName == OpenPath) {
+ return ENODEV;
+ }
+
+ //
+ // Extract the device pathname, convert it to lower case and
+ // put zeros where the "key" is not specified.
+ //
+ TempString1=DeviceName;
+ for (TempString2=OpenPath;TempString2 != FileName ;TempString2++) {
+ //
+ // If about to copy ')' and previous char was '('
+ // put a zero in between.
+ //
+ if (((*TempString2 == ')') && (*(TempString1-1)) == '(')){
+ *TempString1++ = '0';
+ }
+ *TempString1++ = tolower(*TempString2);
+ }
+ *TempString1 = '\0';
+
+ //
+ // Translate the open mode to its equivalent for devices.
+ //
+ DeviceOpenMode = OpenMode;
+
+ if (FileName[0] == '\0') {
+ //
+ // On an attempt to open a device with an invalid OpenMode
+ // return an error.
+ //
+ if (OpenMode > ArcOpenReadWrite) {
+ return EINVAL;
+ }
+ } else {
+
+ //
+ // A file is being opened, set the right Open Mode for the device.
+ //
+ if (OpenMode > ArcOpenReadOnly) {
+ DeviceOpenMode = ArcOpenReadWrite;
+ }
+ }
+
+#if !defined(FAILSAFE_BOOTER) && defined(EISA_PLATFORM)
+ //
+ // Check for OMF protocol.
+ //
+
+ if ( strstr(DeviceName, ")omf(0)" ) != NULL ) {
+ OmfProtocol = TRUE;
+ } else {
+ OmfProtocol = FALSE;
+ }
+#endif
+
+ //
+ // Search for a matching entry in the table of opened devices.
+ //
+ for (DeviceId = 0;DeviceId < SIZE_OF_OPENED_PATHNAME_TABLE;DeviceId++) {
+ if (strcmp(DeviceName,OpenedPathTable[DeviceId].DeviceName)==0) {
+ //
+ // device already opened. Check that it is also opened in
+ // the same mode.
+ //
+ if ((DeviceOpenMode != ArcOpenWriteOnly) && (BlFileTable[DeviceId].Flags.Read != 1)) {
+ continue;
+ }
+ if ((DeviceOpenMode != ArcOpenReadOnly) && (BlFileTable[DeviceId].Flags.Write != 1)) {
+ continue;
+ }
+ //
+ // If opened for the same Mode then just increment reference counter.
+ //
+ OpenedPathTable[DeviceId].ReferenceCounter++;
+ Status = ESUCCESS;
+ break;
+ }
+ }
+ if (DeviceId == SIZE_OF_OPENED_PATHNAME_TABLE) {
+
+ //
+ // Device not opened. Look for a driver that handles this device.
+ //
+
+#if !defined(FAILSAFE_BOOTER) && defined(EISA_PLATFORM)
+ if ( OmfProtocol ) {
+
+ //
+ // omf protocol, let the omf software layer validate the path.
+ // Get a free entry in the file table for the device.
+ //
+
+ if ( Status = FiGetFileTableEntry( &DeviceId ) ) {
+ return Status;
+ }
+
+ BlFileTable[DeviceId].DeviceEntryTable = &OmfEntryTable;
+
+ } else {
+#else
+ {
+#endif
+
+ for (i=0;i < SIZE_OF_LOOKUP_TABLE; i++) {
+ if (DeviceLookupTable[i].DevicePath == NULL) {
+
+ //
+ // Driver not found
+ //
+
+ return ENODEV;
+ }
+ if (strstr(DeviceName,DeviceLookupTable[i].DevicePath) == DeviceName) {
+
+ //
+ // Get a free entry in the file table for the device.
+ //
+
+ if (Status = FiGetFileTableEntry(&DeviceId)) {
+ return Status;
+ }
+
+ //
+ // Set the dispatch table in the file table.
+ //
+
+ BlFileTable[DeviceId].DeviceEntryTable = DeviceLookupTable[i].DispatchTable;
+ break;
+ }
+ }
+
+ //
+ // if end of table, drive not found
+ //
+
+ if ( i == SIZE_OF_LOOKUP_TABLE )
+ {
+ return ENODEV;
+ }
+ }
+
+ //
+ // Call the device specific open routine. Use the DeviceName instead of
+ // the OpenPath so that the drivers always see a lowercase name.
+ //
+
+ Status = (BlFileTable[DeviceId].DeviceEntryTable->Open)(DeviceName,
+ DeviceOpenMode,
+ &DeviceId);
+ if (Status != ESUCCESS) {
+ return Status;
+ }
+
+ //
+ // if the device was successfully opened. Log this device name
+ // and initialize the file table.
+ //
+
+ strcpy(OpenedPathTable[DeviceId].DeviceName,DeviceName);
+ OpenedPathTable[DeviceId].ReferenceCounter = 1;
+
+ //
+ // Set flags in file table.
+ //
+
+ BlFileTable[DeviceId].Flags.Open = 1;
+
+ if (DeviceOpenMode != ArcOpenWriteOnly) {
+ BlFileTable[DeviceId].Flags.Read = 1;
+ }
+ if (DeviceOpenMode != ArcOpenReadOnly) {
+ BlFileTable[DeviceId].Flags.Write = 1;
+ }
+
+ //
+ // Mark this entry in the file table as a device itself.
+ //
+
+ BlFileTable[DeviceId].DeviceId = DEVICE_DEVICE;
+ BlFileTable[DeviceId].StructureContext = NULL;
+ }
+
+ //
+ // If we get here the device was successfully open and DeviceId contains
+ // the entry in the file table for this device.
+ //
+
+ if (FileName[0]) {
+
+ //
+ // Get an entry for the file.
+ //
+
+ if (Status=FiGetFileTableEntry(FileId)) {
+ FwClose( DeviceId );
+ return Status;
+
+#if !defined(FAILSAFE_BOOTER) && defined(EISA_PLATFORM)
+
+ //
+ // check if "omf" file system
+ //
+
+ } else if ( OmfProtocol ) {
+ BlFileTable[ *FileId ].DeviceEntryTable = &OmfFileEntryTable;
+#endif
+
+ //
+ // Check if the device has a recognized file system on it. If not
+ // present, allocate a structure context.
+ //
+
+ } else if (((TmpStructureContext = BlFileTable[DeviceId].StructureContext) == NULL) &&
+ ((TmpStructureContext = FiAllocateFsStructure()) == NULL)) {
+ FwClose( DeviceId );
+ return EMFILE;
+
+ //
+ // Check for FAT filesystem.
+ //
+
+ } else if ((BlFileTable[*FileId].DeviceEntryTable =
+ IsFatFileStructure(DeviceId,TmpStructureContext))
+ != NULL) {
+ BlFileTable[DeviceId].StructureContext = TmpStructureContext;
+
+ //
+ // Check for CD filesystem.
+ //
+
+ } else if ((BlFileTable[*FileId].DeviceEntryTable =
+ IsCdfsFileStructure(DeviceId,TmpStructureContext))
+ != NULL) {
+ BlFileTable[DeviceId].StructureContext = TmpStructureContext;
+
+#if !defined(FAILSAFE_BOOTER) && !defined(ALPHA_FW_KDHOOKS)
+
+//
+// Do not build in this clause if this is a FailSafe Booter build, or
+// if we are building in the kernel debugger stub.
+//
+
+ //
+ // Check for NTFS filesystem.
+ //
+
+ } else if ((BlFileTable[*FileId].DeviceEntryTable =
+ IsNtfsFileStructure(DeviceId,TmpStructureContext))
+ != NULL) {
+ BlFileTable[DeviceId].StructureContext = TmpStructureContext;
+#endif
+
+ } else {
+
+ FiFreeFsStructure(TmpStructureContext);
+ FwClose(DeviceId);
+ FwPrint(FW_FILESYSTEM_NOT_REQ_MSG);
+ return EIO;
+ }
+
+ //
+ // Set the DeviceId in the file table.
+ //
+
+ BlFileTable[*FileId].DeviceId = DeviceId;
+
+ //
+ // Copy the pointer to FatStructureContext from the device entry
+ // to the file entry.
+ //
+
+ BlFileTable[*FileId].StructureContext = BlFileTable[DeviceId].StructureContext;
+ Status = (BlFileTable[*FileId].DeviceEntryTable->Open)(FileName,
+ OpenMode,
+ FileId);
+
+
+ //
+ // If the file could not be opened. Then close the device and
+ // return the error
+ //
+
+ if (Status != ESUCCESS) {
+ FiFreeFsStructure(TmpStructureContext);
+ FwClose(DeviceId);
+ }
+
+ return Status;
+
+ } else {
+
+ //
+ // No file specified return the fid for the device.
+ //
+ *FileId = DeviceId;
+ return Status;
+ }
+}
+
+ARC_STATUS
+FiGetFileTableEntry(
+ OUT PULONG Entry
+ )
+
+/*++
+
+Routine Description:
+
+ This function looks for an unused entry in the FileTable.
+
+Arguments:
+
+ Entry - Pointer to the variable that gets an index for the file table.
+
+Return Value:
+
+ Returns ESUCCESS if a free entry is found
+ or EMFILE if no entry is available.
+
+--*/
+
+{
+ ULONG Index;
+ for (Index=0;Index < BL_FILE_TABLE_SIZE;Index++) {
+ if (BlFileTable[Index].Flags.Open == 0) {
+ *Entry = Index;
+ return ESUCCESS;
+ }
+ }
+ return EMFILE;
+}
+ ULONG
+FiGetFreeLookupEntry (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine looks for the first available entry in the device
+ lookup table, that is the entry where DevicePath is NULL.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns the Index of the first free entry of the DeviceLookupTable
+ or SIZE_OF_LOOKUP_TABLE is the table is full.
+
+
+--*/
+
+{
+ULONG Index;
+ //
+ // Search for the first free entry in the Lookup table
+ //
+ for (Index=0;Index < SIZE_OF_LOOKUP_TABLE;Index++) {
+ if (DeviceLookupTable[Index].DevicePath == NULL) {
+ break;
+ }
+ }
+ return Index;
+}
+
+VOID
+FwIoInitialize1(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the file table used by the firmware to
+ export I/O functions to client programs loaded from the system
+ partition, initializes the I/O entry points in the firmware
+ transfer vector and initializes the display driver.
+
+ Note: This routine is called at phase 1 initialization.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Index;
+ //
+ // Initialize the I/O entry points in the firmware transfer vector.
+ //
+
+ (PARC_CLOSE_ROUTINE)SYSTEM_BLOCK->FirmwareVector[CloseRoutine] = FwClose;
+ (PARC_MOUNT_ROUTINE)SYSTEM_BLOCK->FirmwareVector[MountRoutine] = FwMount;
+ (PARC_OPEN_ROUTINE)SYSTEM_BLOCK->FirmwareVector[OpenRoutine] = FwOpen;
+ (PARC_READ_ROUTINE)SYSTEM_BLOCK->FirmwareVector[ReadRoutine] = FwRead;
+ (PARC_READ_STATUS_ROUTINE)SYSTEM_BLOCK->FirmwareVector[ReadStatusRoutine] =
+ FwGetReadStatus;
+ (PARC_SEEK_ROUTINE)SYSTEM_BLOCK->FirmwareVector[SeekRoutine] = FwSeek;
+ (PARC_WRITE_ROUTINE)SYSTEM_BLOCK->FirmwareVector[WriteRoutine] = FwWrite;
+ (PARC_GET_FILE_INFO_ROUTINE)SYSTEM_BLOCK->FirmwareVector[GetFileInformationRoutine] = FwGetFileInformation;
+ (PARC_SET_FILE_INFO_ROUTINE)SYSTEM_BLOCK->FirmwareVector[SetFileInformationRoutine] = FwSetFileInformation;
+ (PARC_GET_DIRECTORY_ENTRY_ROUTINE)SYSTEM_BLOCK->FirmwareVector[GetDirectoryEntryRoutine] = FwGetDirectoryEntry;
+
+ //
+ // Initialize the file table.
+ //
+
+ for (Index = 0; Index < BL_FILE_TABLE_SIZE; Index += 1) {
+ BlFileTable[Index].Flags.Open = 0;
+ }
+
+ //
+ // Initialize the driver lookup table.
+ //
+ for (Index=0;Index < SIZE_OF_LOOKUP_TABLE;Index++) {
+ DeviceLookupTable[Index].DevicePath = NULL;
+ }
+
+ //
+ // Initialize the table of opened devices.
+ //
+ for (Index = 0;Index < SIZE_OF_OPENED_PATHNAME_TABLE;Index++) {
+ OpenedPathTable[Index].DeviceName[0]='\0';
+ }
+
+ //
+ // Call the Display driver initialization routine
+ //
+ DisplayInitialize(&DeviceLookupTable[0],
+ SIZE_OF_LOOKUP_TABLE);
+ return;
+}
+
+VOID
+FwIoInitialize2(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine calls the device driver initialization routines.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG Index;
+
+ //
+ // Call the Keyboard driver initialization routine
+ //
+ if ((Index=FiGetFreeLookupEntry()) == SIZE_OF_LOOKUP_TABLE) {
+ FwPrint(FW_NOT_ENOUGH_ENTRIES_MSG);
+ } else {
+ KeyboardInitialize(&DeviceLookupTable[Index],
+ SIZE_OF_LOOKUP_TABLE-Index);
+ }
+
+ //
+ // Look for first free entry and call
+ // floppy driver initialization routine
+ //
+
+ if ((Index=FiGetFreeLookupEntry()) == SIZE_OF_LOOKUP_TABLE) {
+ FwPrint(FW_NOT_ENOUGH_ENTRIES_MSG);
+ } else {
+ FloppyInitialize(&DeviceLookupTable[Index],
+ SIZE_OF_LOOKUP_TABLE-Index);
+ }
+
+ //
+ // Initialize the MasterAdapterObject for the pseudo-Hal support
+ // functions in jxhwsup.c.
+ //
+
+ MasterAdapterObject = NULL;
+ for (Index = 0; Index < 8; Index++) {
+ HalpEisaAdapter[Index] = 0;
+ }
+
+ //
+ // Initialize global variables. This fixes a bug where the firmware
+ // will crash after (10/number of SCSI busses) reboots.
+ // Init is done here since aha154x driver calls scsiportinitialize
+ // twice (for isa then mca) so can't init this there.
+ //
+
+ for (ScsiPortCount = 0; ScsiPortCount < 10; ScsiPortCount++) {
+ ScsiPortDeviceObject[ScsiPortCount] = 0;
+ }
+
+ ScsiPortCount = 0;
+
+ //
+ // Call the mini-port driver initialization routine.
+ //
+
+ DriverEntry(NULL, NULL);
+
+ //
+ // Call the scsi driver initialization routine
+ //
+
+ {
+
+ //
+ // This is a temporary bugfix for the FwAddChild failure bug in
+ // scsidisk.c
+ //
+
+ CHAR ComponentPath[10];
+ PCONFIGURATION_COMPONENT ControllerComponent;
+ PCONFIGURATION_COMPONENT ScsiComponent;
+ PCONFIGURATION_COMPONENT NextComponent;
+ PCONFIGURATION_COMPONENT PeripheralComponent;
+
+ //
+ // Search the configuration database for scsi disk and cdrom devices and
+ // delete them.
+ //
+
+ sprintf(ComponentPath,"scsi(%1d)", 0);
+ ScsiComponent = FwGetComponent(ComponentPath);
+
+ if (ScsiComponent != NULL) {
+ if (ScsiComponent->Type == ScsiAdapter) {
+ ControllerComponent = FwGetChild(ScsiComponent);
+
+ while (ControllerComponent != NULL) {
+ NextComponent = FwGetPeer(ControllerComponent);
+
+ if ((ControllerComponent->Type == DiskController) ||
+ (ControllerComponent->Type == CdromController)) {
+
+ PeripheralComponent = FwGetChild(ControllerComponent);
+ if (FwDeleteComponent(PeripheralComponent) == ESUCCESS) {
+ FwDeleteComponent(ControllerComponent);
+ }
+ }
+ ControllerComponent = NextComponent;
+ }
+ }
+ }
+
+ FwPrint(FW_DO_NOT_POWER_OFF_MSG);
+
+ FwSaveConfiguration();
+
+ FwPrint(FW_OK_MSG);
+ FwPrint(FW_CRLF_MSG);
+
+ }
+
+ if ((Index=FiGetFreeLookupEntry()) == SIZE_OF_LOOKUP_TABLE) {
+ FwPrint(FW_NOT_ENOUGH_ENTRIES_MSG);
+ } else {
+ HardDiskInitialize(&DeviceLookupTable[Index],
+ SIZE_OF_LOOKUP_TABLE-Index,
+ NULL);
+ }
+
+ //
+ // Call the serial port driver initialization routine
+ //
+ if ((Index=FiGetFreeLookupEntry()) == SIZE_OF_LOOKUP_TABLE) {
+ FwPrint(FW_NOT_ENOUGH_ENTRIES_MSG);
+ } else {
+ SerialInitialize(&DeviceLookupTable[Index],
+ SIZE_OF_LOOKUP_TABLE-Index);
+ }
+
+ //
+ // Pre allocate memory for the File system structures.
+ //
+
+ FileSystemStructurePool =
+ FwAllocatePool(sizeof(FS_POOL_ENTRY) * FS_POOL_SIZE);
+
+ return;
+}
+
+ PVOID
+FiAllocateFsStructure(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates a File System structure
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns a pointer to the Allocated File System structure or NULL.
+
+--*/
+
+{
+
+ PFS_POOL_ENTRY TmpPointer,Last;
+
+ if (FileSystemStructurePool == NULL) {
+ return NULL;
+ }
+
+ TmpPointer = FileSystemStructurePool;
+
+ Last = FileSystemStructurePool+FS_POOL_SIZE;
+ do {
+ if (TmpPointer->InUse == FALSE) {
+ TmpPointer->InUse = TRUE;
+ return &TmpPointer->Fs;
+ }
+ TmpPointer++;
+ } while (TmpPointer != Last);
+
+ return NULL;
+}
+ VOID
+FiFreeFsStructure(
+ IN PFILE_SYSTEM_STRUCTURE PFs
+ )
+
+/*++
+
+Routine Description:
+
+ This routine frees a File System structure previously allocated.
+
+Arguments:
+
+ PFs pointer to the file system structure to free.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ CONTAINING_RECORD(PFs, FS_POOL_ENTRY, Fs)->InUse = FALSE;
+ return;
+}
diff --git a/private/ntos/fw/alpha/fwkd.c b/private/ntos/fw/alpha/fwkd.c
new file mode 100644
index 000000000..4701f7801
--- /dev/null
+++ b/private/ntos/fw/alpha/fwkd.c
@@ -0,0 +1,699 @@
+#ifdef ALPHA_FW_KDHOOKS
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ fwkd.c
+
+Abstract:
+
+ This module implements the code to interface the firware exception
+ path with the kernel debugger stub.
+
+Author:
+
+ Joe Notarangelo 31-Mar-93
+
+Environment:
+
+ Firmware.
+
+Revision History:
+
+--*/
+
+#include "fwp.h"
+#include "fwpexcpt.h"
+#include "ntosdef.h"
+
+VOID
+FwFrameToKdFrames(
+ PFW_EXCEPTION_FRAME FirmwareFrame,
+ PKTRAP_FRAME TrapFrame,
+ PCONTEXT Context
+ );
+
+VOID
+FwFrameFromKdFrames(
+ PFW_EXCEPTION_FRAME FirmwareFrame,
+ PKTRAP_FRAME TrapFrame,
+ PCONTEXT Context
+ );
+
+VOID
+KeContextFromKframes (
+ IN PKTRAP_FRAME TrapFrame,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN OUT PCONTEXT ContextFrame
+ );
+
+VOID
+KeContextToKframes (
+ IN OUT PKTRAP_FRAME TrapFrame,
+ IN OUT PKEXCEPTION_FRAME ExceptionFrame,
+ IN PCONTEXT ContextFrame,
+ IN ULONG ContextFlags,
+ IN KPROCESSOR_MODE PreviousMode
+ );
+
+
+BOOLEAN
+FwKdProcessBreakpoint(
+ PFW_EXCEPTION_FRAME FirmwareExceptionFrame
+ )
+/*++
+
+Routine Description:
+
+ This function implements the glue logic between the firmware
+ exception path and the kernel debugger stub. It must translate
+ the firmware exception frame to a kernel trap and context frame.
+
+Arguments:
+
+ FirmwareExceptionFrame - supplies a pointer to the firmware exception
+ frame.
+
+Return Value:
+
+ The value TRUE is returned if the breakpoint is processed by the
+ kernel debugger stub, FALSE is returned otherwise.
+
+--*/
+{
+ KTRAP_FRAME TrapFrame;
+ CONTEXT Context;
+ PEXCEPTION_RECORD ExceptionRecord;
+
+
+ //
+ // Translate the firmware exception frame to the frames expected
+ // by the kernel debugger stub.
+ //
+
+ FwFrameToKdFrames( FirmwareExceptionFrame, &TrapFrame, &Context );
+
+
+ ExceptionRecord = (PEXCEPTION_RECORD)&TrapFrame.ExceptionRecord;
+
+ //
+ // Determine if this is a kernel debugger breakpoint, if it is not
+ // return FALSE to indicate that the breakpoint was not handled.
+ //
+
+ if( !KdIsThisAKdTrap(ExceptionRecord,
+ &Context,
+ KernelMode) ) {
+ return FALSE;
+ }
+
+ //
+ // Call the kernel debugger to handle the breakpoint.
+ //
+
+ (VOID)KdpTrap( &TrapFrame,
+ ExceptionRecord,
+ &Context,
+ KernelMode,
+ FALSE );
+
+ //
+ // Transfer the kernel frames back into the firmware frame.
+ //
+
+ FwFrameFromKdFrames( FirmwareExceptionFrame, &TrapFrame, &Context );
+
+ return TRUE;
+}
+
+VOID
+FwFrameToKdFrames(
+ PFW_EXCEPTION_FRAME FirmwareFrame,
+ PKTRAP_FRAME TrapFrame,
+ PCONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ Convert the firmware exception frame to the kernel frames format.
+
+Arguments:
+
+ FirmwareFrame - supplies a pointer to the firmware exception frame.
+
+ TrapFrame - supplies a pointer to the kernel trap frame.
+
+ Context - supplies a pointer to the kernel context
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ PEXCEPTION_RECORD ExceptionRecord;
+ KEXCEPTION_FRAME ExceptionFrame;
+
+ //
+ // Build the kernel trap frame.
+ //
+
+ //
+ // Volatile floating registers.
+ //
+
+ TrapFrame->FltF0 = FirmwareFrame->ExceptionF0;
+ TrapFrame->Fpcr = 0; //not saved by firmware
+ TrapFrame->FltF1 = FirmwareFrame->ExceptionF1;
+
+ TrapFrame->FltF10 = FirmwareFrame->ExceptionF10;
+ TrapFrame->FltF11 = FirmwareFrame->ExceptionF11;
+ TrapFrame->FltF12 = FirmwareFrame->ExceptionF12;
+ TrapFrame->FltF13 = FirmwareFrame->ExceptionF13;
+ TrapFrame->FltF14 = FirmwareFrame->ExceptionF14;
+ TrapFrame->FltF15 = FirmwareFrame->ExceptionF15;
+ TrapFrame->FltF16 = FirmwareFrame->ExceptionF16;
+ TrapFrame->FltF17 = FirmwareFrame->ExceptionF17;
+ TrapFrame->FltF18 = FirmwareFrame->ExceptionF18;
+ TrapFrame->FltF19 = FirmwareFrame->ExceptionF19;
+ TrapFrame->FltF20 = FirmwareFrame->ExceptionF20;
+ TrapFrame->FltF21 = FirmwareFrame->ExceptionF21;
+ TrapFrame->FltF22 = FirmwareFrame->ExceptionF22;
+ TrapFrame->FltF23 = FirmwareFrame->ExceptionF23;
+ TrapFrame->FltF24 = FirmwareFrame->ExceptionF24;
+ TrapFrame->FltF25 = FirmwareFrame->ExceptionF25;
+ TrapFrame->FltF26 = FirmwareFrame->ExceptionF26;
+ TrapFrame->FltF27 = FirmwareFrame->ExceptionF27;
+ TrapFrame->FltF28 = FirmwareFrame->ExceptionF28;
+ TrapFrame->FltF29 = FirmwareFrame->ExceptionF29;
+ TrapFrame->FltF30 = FirmwareFrame->ExceptionF30;
+
+ //
+ // Volatile integer registers.
+ //
+
+ TrapFrame->IntV0 = FirmwareFrame->ExceptionV0;
+ TrapFrame->IntT0 = FirmwareFrame->ExceptionT0;
+ TrapFrame->IntT1 = FirmwareFrame->ExceptionT1;
+ TrapFrame->IntT2 = FirmwareFrame->ExceptionT2;
+ TrapFrame->IntT3 = FirmwareFrame->ExceptionT3;
+ TrapFrame->IntT4 = FirmwareFrame->ExceptionT4;
+ TrapFrame->IntT5 = FirmwareFrame->ExceptionT5;
+ TrapFrame->IntT6 = FirmwareFrame->ExceptionT6;
+ TrapFrame->IntT7 = FirmwareFrame->ExceptionT7;
+
+ TrapFrame->IntFp = FirmwareFrame->ExceptionFp;
+
+ TrapFrame->IntA0 = FirmwareFrame->ExceptionA0;
+ TrapFrame->IntA1 = FirmwareFrame->ExceptionA1;
+ TrapFrame->IntA2 = FirmwareFrame->ExceptionA2;
+ TrapFrame->IntA3 = FirmwareFrame->ExceptionA3;
+
+ TrapFrame->IntA4 = FirmwareFrame->ExceptionA4;
+ TrapFrame->IntA5 = FirmwareFrame->ExceptionA5;
+ TrapFrame->IntT8 = FirmwareFrame->ExceptionT8;
+ TrapFrame->IntT9 = FirmwareFrame->ExceptionT9;
+ TrapFrame->IntT10 = FirmwareFrame->ExceptionT10;
+ TrapFrame->IntT11 = FirmwareFrame->ExceptionT11;
+
+ TrapFrame->IntRa = FirmwareFrame->ExceptionRa;
+ TrapFrame->IntT12 = FirmwareFrame->ExceptionT12;
+ TrapFrame->IntAt = FirmwareFrame->ExceptionAt;
+ TrapFrame->IntGp = FirmwareFrame->ExceptionGp;
+ TrapFrame->IntSp = FirmwareFrame->ExceptionSp;
+
+ //
+ // Exception Record.
+ //
+
+ ExceptionRecord = (PEXCEPTION_RECORD)&TrapFrame->ExceptionRecord;
+
+ ExceptionRecord->ExceptionCode = STATUS_BREAKPOINT;
+ ExceptionRecord->ExceptionAddress = (PVOID)(LONG)
+ FirmwareFrame->ExceptionFaultingInstructionAddress;
+ ExceptionRecord->ExceptionInformation[0] =
+ FirmwareFrame->ExceptionParameter1;
+ ExceptionRecord->ExceptionFlags = 0;
+ ExceptionRecord->ExceptionAddress = NULL;
+ ExceptionRecord->NumberParameters = 0;
+
+ //
+ // Control data.
+ //
+
+ TrapFrame->Fir = FirmwareFrame->ExceptionFaultingInstructionAddress;
+ TrapFrame->Psr = 0;
+ TrapFrame->OldIrql = 0;
+ TrapFrame->PreviousMode = 0;
+
+ //
+ // Build the Context Frame, using the standard kernel routines to
+ // transfer kernel frames to a context frame. This strategy requires
+ // building a local exception frame to pass in to the common routine.
+ //
+
+ ExceptionFrame.IntS0 = FirmwareFrame->ExceptionS0;
+ ExceptionFrame.IntS1 = FirmwareFrame->ExceptionS1;
+ ExceptionFrame.IntS2 = FirmwareFrame->ExceptionS2;
+ ExceptionFrame.IntS3 = FirmwareFrame->ExceptionS3;
+ ExceptionFrame.IntS4 = FirmwareFrame->ExceptionS4;
+ ExceptionFrame.IntS5 = FirmwareFrame->ExceptionS5;
+
+ ExceptionFrame.FltF2 = FirmwareFrame->ExceptionF2;
+ ExceptionFrame.FltF3 = FirmwareFrame->ExceptionF3;
+ ExceptionFrame.FltF4 = FirmwareFrame->ExceptionF4;
+ ExceptionFrame.FltF5 = FirmwareFrame->ExceptionF5;
+ ExceptionFrame.FltF6 = FirmwareFrame->ExceptionF6;
+ ExceptionFrame.FltF7 = FirmwareFrame->ExceptionF7;
+ ExceptionFrame.FltF8 = FirmwareFrame->ExceptionF8;
+ ExceptionFrame.FltF9 = FirmwareFrame->ExceptionF9;
+
+ Context->ContextFlags = CONTEXT_FULL;
+ KeContextFromKframes( TrapFrame, &ExceptionFrame, Context );
+
+}
+
+VOID
+FwFrameFromKdFrames(
+ PFW_EXCEPTION_FRAME FirmwareFrame,
+ PKTRAP_FRAME TrapFrame,
+ PCONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ Convert the firmware exception frame to the kernel frames format.
+
+Arguments:
+
+ FirmwareFrame - supplies a pointer to the firmware exception frame.
+
+ TrapFrame - supplies a pointer to the kernel trap frame.
+
+ Context - supplies a pointer to the kernel context
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ KEXCEPTION_FRAME ExceptionFrame;
+
+//
+// Build the kernel frames (trap and exception) from the
+// context frame using the standard kernel routines.
+//
+
+ KeContextToKframes( TrapFrame,
+ &ExceptionFrame,
+ Context,
+ CONTEXT_FULL,
+ KernelMode );
+
+//
+// Extract the non-volatile register state from the ExceptionFrame
+// and re-populate the firmware frame.
+//
+
+ FirmwareFrame->ExceptionS0 = ExceptionFrame.IntS0;
+ FirmwareFrame->ExceptionS1 = ExceptionFrame.IntS1;
+ FirmwareFrame->ExceptionS2 = ExceptionFrame.IntS2;
+ FirmwareFrame->ExceptionS3 = ExceptionFrame.IntS3;
+ FirmwareFrame->ExceptionS4 = ExceptionFrame.IntS4;
+ FirmwareFrame->ExceptionS5 = ExceptionFrame.IntS5;
+
+ FirmwareFrame->ExceptionF2 = ExceptionFrame.FltF2;
+ FirmwareFrame->ExceptionF3 = ExceptionFrame.FltF3;
+ FirmwareFrame->ExceptionF4 = ExceptionFrame.FltF4;
+ FirmwareFrame->ExceptionF5 = ExceptionFrame.FltF5;
+ FirmwareFrame->ExceptionF6 = ExceptionFrame.FltF6;
+ FirmwareFrame->ExceptionF7 = ExceptionFrame.FltF7;
+ FirmwareFrame->ExceptionF8 = ExceptionFrame.FltF8;
+ FirmwareFrame->ExceptionF9 = ExceptionFrame.FltF9;
+
+//
+// Extract the volatile register state from the TrapFrame and
+// re-populate the firmware frame.
+//
+
+ //
+ // Volatile floating registers.
+ //
+
+ FirmwareFrame->ExceptionF0 = TrapFrame->FltF0;
+ FirmwareFrame->ExceptionF1 = TrapFrame->FltF1;
+
+ FirmwareFrame->ExceptionF10 = TrapFrame->FltF10;
+ FirmwareFrame->ExceptionF11 = TrapFrame->FltF11;
+ FirmwareFrame->ExceptionF12 = TrapFrame->FltF12;
+ FirmwareFrame->ExceptionF13 = TrapFrame->FltF13;
+ FirmwareFrame->ExceptionF14 = TrapFrame->FltF14;
+ FirmwareFrame->ExceptionF15 = TrapFrame->FltF15;
+ FirmwareFrame->ExceptionF16 = TrapFrame->FltF16;
+ FirmwareFrame->ExceptionF17 = TrapFrame->FltF17;
+ FirmwareFrame->ExceptionF18 = TrapFrame->FltF18;
+ FirmwareFrame->ExceptionF19 = TrapFrame->FltF19;
+ FirmwareFrame->ExceptionF20 = TrapFrame->FltF20;
+ FirmwareFrame->ExceptionF21 = TrapFrame->FltF21;
+ FirmwareFrame->ExceptionF22 = TrapFrame->FltF22;
+ FirmwareFrame->ExceptionF23 = TrapFrame->FltF23;
+ FirmwareFrame->ExceptionF24 = TrapFrame->FltF24;
+ FirmwareFrame->ExceptionF25 = TrapFrame->FltF25;
+ FirmwareFrame->ExceptionF26 = TrapFrame->FltF26;
+ FirmwareFrame->ExceptionF27 = TrapFrame->FltF27;
+ FirmwareFrame->ExceptionF28 = TrapFrame->FltF28;
+ FirmwareFrame->ExceptionF29 = TrapFrame->FltF29;
+ FirmwareFrame->ExceptionF30 = TrapFrame->FltF30;
+
+ //
+ // Volatile integer registers.
+ //
+
+ FirmwareFrame->ExceptionV0 = TrapFrame->IntV0;
+ FirmwareFrame->ExceptionT0 = TrapFrame->IntT0;
+ FirmwareFrame->ExceptionT1 = TrapFrame->IntT1;
+ FirmwareFrame->ExceptionT2 = TrapFrame->IntT2;
+ FirmwareFrame->ExceptionT3 = TrapFrame->IntT3;
+ FirmwareFrame->ExceptionT4 = TrapFrame->IntT4;
+ FirmwareFrame->ExceptionT5 = TrapFrame->IntT5;
+ FirmwareFrame->ExceptionT6 = TrapFrame->IntT6;
+ FirmwareFrame->ExceptionT7 = TrapFrame->IntT7;
+
+ FirmwareFrame->ExceptionFp = TrapFrame->IntFp;
+
+ FirmwareFrame->ExceptionA0 = TrapFrame->IntA0;
+ FirmwareFrame->ExceptionA1 = TrapFrame->IntA1;
+ FirmwareFrame->ExceptionA2 = TrapFrame->IntA2;
+ FirmwareFrame->ExceptionA3 = TrapFrame->IntA3;
+
+ FirmwareFrame->ExceptionA4 = TrapFrame->IntA4;
+ FirmwareFrame->ExceptionA5 = TrapFrame->IntA5;
+ FirmwareFrame->ExceptionT8 = TrapFrame->IntT8;
+ FirmwareFrame->ExceptionT9 = TrapFrame->IntT9;
+ FirmwareFrame->ExceptionT10 = TrapFrame->IntT10;
+ FirmwareFrame->ExceptionT11 = TrapFrame->IntT11;
+
+ FirmwareFrame->ExceptionRa = TrapFrame->IntRa;
+ FirmwareFrame->ExceptionT12 = TrapFrame->IntT12;
+ FirmwareFrame->ExceptionAt = TrapFrame->IntAt;
+ FirmwareFrame->ExceptionGp = TrapFrame->IntGp;
+ FirmwareFrame->ExceptionSp = TrapFrame->IntSp;
+
+
+ //
+ // Control data.
+ //
+
+ FirmwareFrame->ExceptionFaultingInstructionAddress = TrapFrame->Fir;
+
+ return;
+}
+
+
+VOID
+KeContextFromKframes (
+ IN PKTRAP_FRAME TrapFrame,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN OUT PCONTEXT ContextFrame
+ )
+
+/*++
+
+Routine Description:
+
+ This routine moves the selected contents of the specified trap and exception
+ frames into the specified context frame according to the specified context
+ flags.
+
+Arguments:
+
+ TrapFrame - Supplies a pointer to a trap frame from which volatile context
+ should be copied into the context record.
+
+ ExceptionFrame - Supplies a pointer to an exception frame from which
+ context should be copied into the context record.
+
+ ContextFrame - Supplies a pointer to the context frame that receives the
+ context copied from the trap and exception frames.
+
+Return Value:
+
+ None.
+
+Implementation Notes:
+
+ The mix of structure element assignments and memory copies in the code
+ below is completely dependent on the layout of the context structure.
+
+ Since this code is not executed often, it is optimized for minimum size
+ (memory copies), rather than maximum speed (individual assignments).
+
+--*/
+
+{
+
+ //
+ // Set control information if specified.
+ //
+
+ if ((ContextFrame->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) {
+
+ //
+ // Set integer register gp, ra, sp, FIR, and PSR from trap frame.
+ //
+
+ ContextFrame->IntGp = TrapFrame->IntGp;
+ ContextFrame->IntSp = TrapFrame->IntSp;
+ ContextFrame->IntRa = TrapFrame->IntRa;
+ ContextFrame->Fir = TrapFrame->Fir;
+ ContextFrame->Psr = TrapFrame->Psr;
+ }
+
+ //
+ // Set integer register contents if specified.
+ //
+
+ if ((ContextFrame->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) {
+
+ //
+ // Set volatile integer registers v0 and t0 - t7 from trap frame.
+ //
+
+ RtlMoveMemory(&ContextFrame->IntV0, &TrapFrame->IntV0,
+ sizeof(ULONGLONG) * 9);
+
+ //
+ // Set nonvolatile integer registers s0 - s5 from exception frame.
+ //
+
+ RtlMoveMemory(&ContextFrame->IntS0, &ExceptionFrame->IntS0,
+ sizeof(ULONGLONG) * 6);
+
+ //
+ // Set volatile integer registers a0 - a3, a4 - a5, and t8 - t11
+ // from trap frame.
+ //
+
+ RtlMoveMemory(&ContextFrame->IntA0, &TrapFrame->IntA0,
+ sizeof(ULONGLONG) * 4);
+ ContextFrame->IntA4 = TrapFrame->IntA4;
+ ContextFrame->IntA5 = TrapFrame->IntA5;
+ RtlMoveMemory(&ContextFrame->IntT8, &TrapFrame->IntT8,
+ sizeof(ULONGLONG) * 4);
+
+ //
+ // Set volatile integer registers fp, t12 and at from trap frame.
+ // Set integer register zero.
+ //
+
+ ContextFrame->IntFp = TrapFrame->IntFp;
+ ContextFrame->IntT12 = TrapFrame->IntT12;
+ ContextFrame->IntAt = TrapFrame->IntAt;
+ ContextFrame->IntZero = 0;
+ }
+
+ //
+ // Set floating register contents if specified.
+ //
+
+ if ((ContextFrame->ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT) {
+
+ //
+ // Set volatile floating registers f0 - f1 from trap frame.
+ // Set volatile floating registers f10 - f30 from trap frame.
+ // Set floating zero register f31 to 0.
+ //
+
+ ContextFrame->FltF0 = TrapFrame->FltF0;
+ ContextFrame->FltF1 = TrapFrame->FltF1;
+ RtlMoveMemory(&ContextFrame->FltF10, &TrapFrame->FltF10,
+ sizeof(ULONGLONG) * 21);
+ ContextFrame->FltF31 = 0;
+
+ //
+ // Set nonvolatile floating registers f2 - f9 from exception frame.
+ //
+
+ RtlMoveMemory(&ContextFrame->FltF2, &ExceptionFrame->FltF2,
+ sizeof(ULONGLONG) * 8);
+
+ //
+ // Set floating point control register from trap frame.
+ //
+
+ ContextFrame->Fpcr = TrapFrame->Fpcr;
+ }
+
+ return;
+}
+
+VOID
+KeContextToKframes (
+ IN OUT PKTRAP_FRAME TrapFrame,
+ IN OUT PKEXCEPTION_FRAME ExceptionFrame,
+ IN PCONTEXT ContextFrame,
+ IN ULONG ContextFlags,
+ IN KPROCESSOR_MODE PreviousMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine moves the selected contents of the specified context frame
+ into the specified trap and exception frames according to the specified
+ context flags.
+
+Arguments:
+
+ TrapFrame - Supplies a pointer to a trap frame that receives the volatile
+ context from the context record.
+
+ ExceptionFrame - Supplies a pointer to an exception frame that receives
+ the nonvolatile context from the context record.
+
+ ContextFrame - Supplies a pointer to a context frame that contains the
+ context that is to be copied into the trap and exception frames.
+
+ ContextFlags - Supplies the set of flags that specify which parts of the
+ context frame are to be copied into the trap and exception frames.
+
+ PreviousMode - Supplies the processor mode for which the trap and exception
+ frames are being built.
+
+Return Value:
+
+ None.
+
+Implementation Notes:
+
+ The mix of structure element assignments and memory copies in the code
+ below is completely dependent on the layout of the context structure.
+
+ Since this code is not executed often, it is optimized for minimum size
+ (memory copies), rather than maximum speed (individual assignments).
+
+--*/
+
+{
+
+ //
+ // Set control information if specified.
+ //
+
+ if ((ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) {
+
+ //
+ // Set integer register gp, sp, ra, FIR, and PSR in trap frame.
+ //
+
+ TrapFrame->IntGp = ContextFrame->IntGp;
+ TrapFrame->IntSp = ContextFrame->IntSp;
+ TrapFrame->IntRa = ContextFrame->IntRa;
+ TrapFrame->Fir = ContextFrame->Fir;
+ TrapFrame->Psr = SANITIZE_PSR(ContextFrame->Psr, PreviousMode);
+ }
+
+ //
+ // Set integer register contents if specified.
+ //
+
+ if ((ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) {
+
+ //
+ // Set volatile integer registers v0 and t0 - t7 in trap frame.
+ //
+
+ RtlMoveMemory(&TrapFrame->IntV0, &ContextFrame->IntV0,
+ sizeof(ULONGLONG) * 9);
+
+ //
+ // Set nonvolatile integer registers s0 - s5 in exception frame.
+ //
+
+ RtlMoveMemory(&ExceptionFrame->IntS0, &ContextFrame->IntS0,
+ sizeof(ULONGLONG) * 6);
+
+ //
+ // Set volatile integer registers a0 - a3, a4 - a5, and t8 - t11
+ // in trap frame.
+ //
+
+ RtlMoveMemory(&TrapFrame->IntA0, &ContextFrame->IntA0,
+ sizeof(ULONGLONG) * 4);
+ TrapFrame->IntA4 = ContextFrame->IntA4;
+ TrapFrame->IntA5 = ContextFrame->IntA5;
+ RtlMoveMemory(&TrapFrame->IntT8, &ContextFrame->IntT8,
+ sizeof(ULONGLONG) * 4);
+
+ //
+ // Set volatile integer registers fp, t12 and at in trap frame.
+ //
+
+ TrapFrame->IntFp = ContextFrame->IntFp;
+ TrapFrame->IntT12 = ContextFrame->IntT12;
+ TrapFrame->IntAt = ContextFrame->IntAt;
+ }
+
+ //
+ // Set floating register contents if specified.
+ //
+
+ if ((ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT) {
+
+ //
+ // Set volatile floating registers f0 - f1 in trap frame.
+ // Set volatile floating registers f10 - f30 in trap frame.
+ //
+
+ TrapFrame->FltF0 = ContextFrame->FltF0;
+ TrapFrame->FltF1 = ContextFrame->FltF1;
+ RtlMoveMemory(&TrapFrame->FltF10, &ContextFrame->FltF10,
+ sizeof(ULONGLONG) * 21);
+
+ //
+ // Set nonvolatile floating registers f2 - f9 in exception frame.
+ //
+
+ RtlMoveMemory(&ExceptionFrame->FltF2, &ContextFrame->FltF2,
+ sizeof(ULONGLONG) * 8);
+
+ //
+ // Set floating point control register in trap frame.
+ //
+
+ TrapFrame->Fpcr = SANITIZE_FPCR(ContextFrame->Fpcr, PreviousMode);
+ }
+
+ return;
+}
+
+#endif
diff --git a/private/ntos/fw/alpha/fwload.c b/private/ntos/fw/alpha/fwload.c
new file mode 100644
index 000000000..bb78077ba
--- /dev/null
+++ b/private/ntos/fw/alpha/fwload.c
@@ -0,0 +1,1035 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ fwload.c
+
+Abstract:
+
+ This module implements the ARC software loadable functions.
+
+Author:
+
+ Lluis Abello (lluis) 19-Sep-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ 15-June-1992 John DeRosa [DEC]
+
+ Added Alpha/Jensen hooks. These changes will themselves change
+ as the coff file format work is completed.
+
+ PENDING WORK: MIPS relocation types, structures.
+
+--*/
+
+#include "fwp.h"
+#include "string.h"
+#include "ntimage.h"
+#include "fwstring.h"
+
+//
+// Declare external variables.
+//
+
+#ifdef ALPHA_FW_KDHOOKS
+extern BOOLEAN BreakAfterLoad;
+#endif
+
+#define MAX_ARGUMENT ( 512 - sizeof(ULONG) - 16*sizeof(PUCHAR) )
+
+typedef struct _SAVED_ARGUMENTS {
+ ULONG Argc;
+ PUCHAR Argv[16];
+ UCHAR Arguments[MAX_ARGUMENT];
+} SAVED_ARGUMENTS, *PSAVED_ARGUMENTS;
+
+//
+// Static variables.
+//
+
+PSAVED_ARGUMENTS PSavedArgs;
+ULONG FwTemporaryStack;
+ULONG FwActualBasePage;
+ULONG FwPageCount;
+BOOLEAN MatchedReflo;
+
+ARC_STATUS
+FwExecute(
+ IN PCHAR Path,
+ IN ULONG Argc,
+ IN PCHAR Argv[],
+ IN PCHAR Envp[]
+ );
+
+
+//
+// s_flags values
+//
+
+#define STYP_REG 0x00000000
+#define STYP_TEXT 0x00000020
+#define STYP_INIT 0x80000000
+#define STYP_RDATA 0x00000100
+#define STYP_DATA 0x00000040
+#define STYP_LIT8 0x08000000
+#define STYP_LIT4 0x10000000
+#define STYP_SDATA 0x00000200
+#define STYP_SBSS 0x00000080
+#define STYP_BSS 0x00000400
+#define STYP_LIB 0x40000000
+#define STYP_UCODE 0x00000800
+#define S_NRELOC_OVFL 0x20000000
+
+//
+// Section numbers for local relocation entries
+//
+
+#define R_SN_TEXT 1
+#define R_SN_INIT 7
+#define R_SN_RDATA 2
+#define R_SN_DATA 3
+#define R_SN_SDATA 4
+#define R_SN_SBSS 5
+#define R_SN_BSS 6
+#define R_SN_LIT8 8
+#define R_SN_LIT4 9
+#define R_SN_MAX 10
+
+typedef struct _MIPS_RELOCATION_TYPE {
+ ULONG SymbolIndex:24;
+ ULONG Reserved:3;
+ ULONG Type:4;
+ ULONG External:1;
+} MIPS_RELOCATION_TYPE, *PMIPS_RELOCATION_TYPE;
+
+typedef struct _MIPS_RELOCATION_ENTRY {
+ ULONG VirtualAddress;
+ MIPS_RELOCATION_TYPE Type;
+} MIPS_RELOCATION_ENTRY, *PMIPS_RELOCATION_ENTRY;
+
+typedef struct _MIPS_SYMBOLIC_HEADER {
+ SHORT Magic;
+ SHORT VersionStamp;
+ ULONG NumOfLineNumberEntries;
+ ULONG BytesForLineNumberEntries;
+ ULONG PointerToLineNumberEntries;
+ ULONG NumOfDenseNumbers;
+ ULONG PointerToDenseNumbers;
+ ULONG NumOfProcedures;
+ ULONG PointerToProcedures;
+ ULONG NumOfLocalSymbols;
+ ULONG PointerToLocalSymbols;
+ ULONG NumOfOptimizationEntries;
+ ULONG PointerToOptimizationEntries;
+ ULONG NumOfAuxSymbols;
+ ULONG PointerToAuxSymbols;
+ ULONG NumOfLocalStrings;
+ ULONG PointerToLocalStrings;
+ ULONG NumOfExternalStrings;
+ ULONG PointerToExternalStrings;
+ ULONG NumOfFileDescriptors;
+ ULONG PointerToFileDescriptors;
+ ULONG NumOfRelativeFileDescriptors;
+ ULONG PointerToRelativeFileDescriptors;
+ ULONG NumOfExternalSymbols;
+ ULONG PointerToExternalSymbols;
+} MIPS_SYMBOLIC_HEADER, *PMIPS_SYMBOLIC_HEADER;
+
+typedef struct _MIPS_LOCAL_SYMBOL {
+ ULONG IndexToSymbolString;
+ ULONG Value;
+ ULONG Type:6;
+ ULONG StorageClass:5;
+ ULONG Reserved:1;
+ ULONG Index:20;
+} MIPS_LOCAL_SYMBOL, *PMIPS_LOCAL_SYMBOL;
+
+//
+// Types for external symbols
+//
+#define EST_NIL 0
+#define EST_GLOBAL 1
+#define EST_STATIC 2
+#define EST_PARAM 3
+#define EST_LOCAL 4
+#define EST_LABEL 5
+#define EST_PROC 6
+#define EST_BLOCK 7
+#define EST_END 8
+#define EST_MEMBER 9
+#define EST_TYPEDEF 10
+#define EST_FILE 11
+#define EST_STATICPROC 14
+#define EST_CONSTANT 15
+
+//
+// Storage class for external symbols
+//
+#define ESSC_NIL 0
+#define ESSC_TEXT 1
+#define ESSC_DATA 2
+#define ESSC_BSS 3
+#define ESSC_REGISTER 4
+#define ESSC_ABS 5
+#define ESSC_UNDEFINED 6
+#define ESSC_BITS 8
+#define ESSC_DBX 9
+#define ESSC_REGIMAX 10
+#define ESSC_INFO 11
+#define ESSC_USER_STRUCT 12
+#define ESSC_SDATA 13
+#define ESSC_SBSS 14
+#define ESSC_SRDATA 15
+#define ESSC_VAR 16
+#define ESSC_COMMON 17
+#define ESSC_SCOMMON 18
+#define ESSC_VARREGISTER 19
+#define ESSC_VARIANT 20
+#define ESSC_SUNDEFINED 21
+#define ESSC_INIT 22
+
+typedef struct _MIPS_EXTERNAL_SYMBOL {
+ USHORT Reserved;
+ USHORT PointerToFileDescriptor;
+ MIPS_LOCAL_SYMBOL Symbol;
+} MIPS_EXTERNAL_SYMBOL, *PMIPS_EXTERNAL_SYMBOL;
+
+typedef struct _SECTION_RELOCATION_ENTRY {
+ ULONG FixupValue;
+ ULONG PointerToRelocations;
+ USHORT NumberOfRelocations;
+} SECTION_RELOCATION_ENTRY, *PSECTION_RELOCATION_ENTRY;
+
+typedef
+VOID
+(*PTRANSFER_ROUTINE) (
+ IN ULONG Argc,
+ IN PCHAR Argv[],
+ IN PCHAR Envp[]
+ );
+
+ARC_STATUS
+FwRelocateImage (
+ IN ULONG FileId,
+ PSECTION_RELOCATION_ENTRY RelocationTable
+ );
+
+VOID
+FwGenerateDescriptor (
+ IN PFW_MEMORY_DESCRIPTOR MemoryDescriptor,
+ IN MEMORY_TYPE MemoryType,
+ IN ULONG BasePage,
+ IN ULONG PageCount
+ );
+
+
+ARC_STATUS
+FwLoad (
+ IN PCHAR ImagePath,
+ IN ULONG TopAddress,
+ OUT PULONG EntryAddress,
+ OUT PULONG LowAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This routine attempts to load the specified file from the specified
+ device.
+
+Arguments:
+
+ ImagePath - Supplies a pointer to the path of the file to load.
+
+ TopAddress - Supplies the top address of a region of memory into which
+ the file is to be loaded.
+
+ EntryAddress - Supplies a pointer to a variable to receive the entry point
+ of the image, if defined.
+
+ LowAddress - Supplies a pointer to a variable to receive the low address
+ of the loaded file.
+
+Return Value:
+
+ ESUCCESS is returned if the specified image file is loaded
+ successfully. Otherwise, an unsuccessful status is returned
+ that describes the reason for failure.
+
+--*/
+
+{
+ SECTION_RELOCATION_ENTRY RelocationTable[R_SN_MAX];
+ ULONG ActualBase;
+ ULONG SectionBase;
+ ULONG SectionOffset;
+ ULONG SectionIndex;
+ ULONG Count;
+ PIMAGE_FILE_HEADER FileHeader;
+ ULONG FileId;
+ ULONG Index;
+ UCHAR LocalBuffer[SECTOR_SIZE+32];
+ PUCHAR LocalPointer;
+ ULONG NumberOfSections;
+ PIMAGE_OPTIONAL_HEADER OptionalHeader;
+ PIMAGE_SECTION_HEADER SectionHeader;
+ ARC_STATUS Status;
+ LARGE_INTEGER SeekPosition;
+ ULONG SectionFlags;
+
+ //
+ // Zero The relocation table
+ //
+ RtlZeroMemory((PVOID)RelocationTable,sizeof(RelocationTable));
+
+ //
+ // Align the buffer on a Dcache line size.
+ //
+
+ LocalPointer = (PVOID) ((ULONG) ((PCHAR) LocalBuffer + KeGetDcacheFillSize() - 1)
+ & ~(KeGetDcacheFillSize() - 1));
+
+ //
+ // Set the image start address to null.
+ //
+
+ *EntryAddress = 0;
+
+ //
+ // Attempt to open the load file.
+ //
+
+ Status = ArcOpen(ImagePath, ArcOpenReadOnly, &FileId);
+ if (Status != ESUCCESS) {
+ return Status;
+ }
+
+ //
+ // Read the image header from the file.
+ //
+
+ Status = ArcRead(FileId, LocalPointer, SECTOR_SIZE, &Count);
+ if (Status != ESUCCESS) {
+ ArcClose(FileId);
+ return Status;
+ }
+
+ //
+ // Get a pointer to the file header and begin processing it.
+ //
+
+ FileHeader = (PIMAGE_FILE_HEADER)LocalPointer;
+ OptionalHeader =
+ (PIMAGE_OPTIONAL_HEADER)(LocalPointer + sizeof(IMAGE_FILE_HEADER));
+ SectionHeader =
+ (PIMAGE_SECTION_HEADER)(LocalPointer + sizeof(IMAGE_FILE_HEADER) +
+ FileHeader->SizeOfOptionalHeader);
+
+ //
+ // If the image file is not the specified type, then return bad image
+ // type status.
+ //
+
+ //
+ // During NT/Alpha development, the magic number definition in Alpha
+ // images was incremented by one. Old and new images should both still
+ // be loadable by the firmware. So to facilitate support of older
+ // standalone images, as a temporary hack the firmware will load both
+ // old and new Alpha AXP image file types.
+ //
+
+ if (!((FileHeader->Machine == IMAGE_FILE_MACHINE_R3000) ||
+ (FileHeader->Machine == IMAGE_FILE_MACHINE_R4000) ||
+ (FileHeader->Machine == (IMAGE_FILE_MACHINE_ALPHA - 1)) ||
+ (FileHeader->Machine == IMAGE_FILE_MACHINE_ALPHA)) ||
+ ((FileHeader->Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE) == 0)) {
+ ArcClose(FileId);
+ return EBADF;
+ }
+
+ //
+ // If the image cannot be relocated, set the ActualBase to the code base,
+ // and compute the image size by subtracting the code base from the data
+ // base plus the size of the data. If the image can be relocated,
+ // set ActualBase to the TopAddress minus the image size, and compute the
+ // image size by adding the size of the code, initialized data, and
+ // uninitialized data.
+ //
+
+ NumberOfSections = FileHeader->NumberOfSections;
+
+ if ((FileHeader->Characteristics & IMAGE_FILE_RELOCS_STRIPPED) != 0) {
+ ActualBase = OptionalHeader->BaseOfCode;
+ FwPageCount = (OptionalHeader->BaseOfData + OptionalHeader->SizeOfInitializedData) -
+ ActualBase;
+ } else {
+ FwPageCount = OptionalHeader->SizeOfCode +
+ OptionalHeader->SizeOfInitializedData +
+ OptionalHeader->SizeOfUninitializedData;
+
+ ActualBase = (TopAddress - FwPageCount) & ~(PAGE_SIZE - 1);
+ }
+
+ //
+ // Convert ActualBasePage and PageCount to be in units of pages instead of
+ // bytes.
+ //
+
+ FwActualBasePage = (ActualBase & 0x1fffffff) >> PAGE_SHIFT;
+
+ if (strcmp((PCHAR)&SectionHeader[NumberOfSections - 1].Name, ".debug") == 0) {
+ NumberOfSections -= 1;
+ FwPageCount -= SectionHeader[NumberOfSections].SizeOfRawData;
+ }
+ FwPageCount = (FwPageCount + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+ *LowAddress = ActualBase | KSEG0_BASE;
+
+ //
+ // Return the entry address to the caller.
+ //
+
+ *EntryAddress = ((ActualBase | KSEG0_BASE) +
+ (OptionalHeader->AddressOfEntryPoint - OptionalHeader->BaseOfCode)
+ );
+
+
+ //
+ // Scan through the sections and either read them into memory or clear
+ // the memory as appropriate.
+ //
+
+ SectionOffset = 0;
+ for (Index = 0; Index < NumberOfSections; Index += 1) {
+
+ //
+ // Compute the destination address for the current section.
+ //
+ if ((FileHeader->Characteristics & IMAGE_FILE_RELOCS_STRIPPED) != 0) {
+ SectionBase = SectionHeader->VirtualAddress | KSEG0_BASE;
+ } else {
+ SectionBase = ActualBase + SectionOffset;
+ //
+ // Store the section relocation information in the table.
+ //
+ SectionFlags = SectionHeader->Characteristics;
+ if (SectionFlags & STYP_TEXT) {
+ SectionIndex = R_SN_TEXT;
+ } else if (SectionFlags & STYP_INIT) {
+ SectionIndex = R_SN_INIT;
+ } else if (SectionFlags & STYP_RDATA) {
+ SectionIndex = R_SN_RDATA;
+ } else if (SectionFlags & STYP_DATA) {
+ SectionIndex = R_SN_DATA;
+ } else if (SectionFlags & STYP_SDATA) {
+ SectionIndex = R_SN_SDATA;
+ } else if (SectionFlags & STYP_SBSS) {
+ SectionIndex = R_SN_SBSS;
+ } else if (SectionFlags & STYP_BSS) {
+ SectionIndex = R_SN_BSS;
+ } else {
+ VenPrint(FW_UNKNOWN_SECTION_TYPE_MSG);
+ return EBADF;
+ }
+ RelocationTable[SectionIndex].PointerToRelocations = SectionHeader->PointerToRelocations;
+ RelocationTable[SectionIndex].NumberOfRelocations = SectionHeader->NumberOfRelocations;
+ RelocationTable[SectionIndex].FixupValue = SectionBase - SectionHeader->VirtualAddress;
+ }
+
+ //
+ // If the section is code, initialized data, or other, then read
+ // the code or data into memory.
+ //
+
+ if ((SectionHeader->Characteristics &
+ (STYP_TEXT | STYP_INIT | STYP_RDATA | STYP_DATA | STYP_SDATA)) != 0) {
+
+ SeekPosition.LowPart = SectionHeader->PointerToRawData;
+ SeekPosition.HighPart = 0;
+ Status = ArcSeek(FileId,
+ &SeekPosition,
+ SeekAbsolute);
+
+ if (Status != ESUCCESS) {
+ break;
+ }
+
+ Status = ArcRead(FileId,
+ (PVOID)SectionBase,
+ SectionHeader->SizeOfRawData,
+ &Count);
+
+ if (Status != ESUCCESS) {
+ break;
+ }
+
+ //
+ // Set the offset of the next section
+ //
+ SectionOffset += SectionHeader->SizeOfRawData;
+
+ //
+ // If the section is uninitialized data, then zero the specifed memory.
+ //
+
+ } else if ((SectionHeader->Characteristics & (STYP_BSS | STYP_SBSS)) != 0) {
+
+ RtlZeroMemory((PVOID)(SectionBase), SectionHeader->SizeOfRawData);
+
+ //
+ // Set the offset of the next section
+ //
+
+ SectionOffset += SectionHeader->SizeOfRawData;
+
+ }
+
+ SectionHeader += 1;
+ }
+
+ //
+ // If code has to be relocated do so.
+ //
+ if ((FileHeader->Characteristics & IMAGE_FILE_RELOCS_STRIPPED) == 0) {
+ Status=FwRelocateImage(FileId,RelocationTable);
+
+ //
+ // Flush the data cache.
+ //
+
+ HalSweepDcache();
+ }
+ //
+ // Close file and return completion status.
+ //
+ ArcClose(FileId);
+ if (Status == ESUCCESS) {
+
+ //
+ // Flush the instruction cache.
+ //
+
+ HalSweepIcache();
+
+ }
+ return Status;
+}
+
+ARC_STATUS
+FwRelocateImage (
+ IN ULONG FileId,
+ PSECTION_RELOCATION_ENTRY RelocationTable
+ )
+
+/*++
+
+Routine Description:
+
+ This routine relocates an image file that was not loaded into memory
+ at the prefered address.
+
+Arguments:
+
+ FileId - Supplies the file identifier for the image file.
+
+ RelocationTable - Supplies a pointer to a table of section relocation info.
+
+Return Value:
+
+ ESUCCESS is returned in the scan is successful. Otherwise, return an
+ unsuccessful status.
+
+--*/
+
+{
+
+ PULONG FixupAddress;
+ PUSHORT FixupAddressHi;
+ ULONG FixupValue;
+ ULONG Index,Section;
+ ULONG Count;
+ ULONG NumberOfRelocations;
+ PMIPS_RELOCATION_ENTRY RelocationEntry;
+ UCHAR LocalBuffer[SECTOR_SIZE+32];
+ PUCHAR LocalPointer;
+ ULONG Offset;
+ ARC_STATUS Status;
+ MIPS_EXTERNAL_SYMBOL MipsExternalSymbol;
+ ULONG PointerToSymbolicHeader;
+ ULONG PointerToExternalSymbols;
+ ULONG NumberOfExternalSymbols;
+ LARGE_INTEGER SeekPosition;
+ BOOLEAN MatchedReflo;
+
+ //
+ // Align the buffer on a Dcache line size.
+ //
+
+ LocalPointer = (PVOID) ((ULONG) ((PCHAR) LocalBuffer + KeGetDcacheFillSize() - 1)
+ & ~(KeGetDcacheFillSize() - 1));
+
+ //
+ // Read the File Header To find out where the symbols are.
+ //
+
+ SeekPosition.LowPart = 0;
+ SeekPosition.HighPart = 0;
+
+ if ((Status = ArcSeek(FileId,&SeekPosition,SeekAbsolute)) != ESUCCESS) {
+ return Status;
+ }
+
+ if ((Status = ArcRead(FileId,LocalPointer,SECTOR_SIZE,&Count)) != ESUCCESS) {
+ return Status;
+ }
+
+ PointerToSymbolicHeader = ((PIMAGE_FILE_HEADER)LocalPointer)->PointerToSymbolTable;
+ // SizeOfSymbolicHeader = ((PIMAGE_FILE_HEADER)LocalPointer)->NumberOfSymbols;
+
+ //
+ // Read the symbolic header to find out where the external symbols are.
+ //
+
+ SeekPosition.LowPart = PointerToSymbolicHeader;
+
+ if ((Status = ArcSeek(FileId,&SeekPosition ,SeekAbsolute)) != ESUCCESS) {
+ return Status;
+ }
+
+ if ((Status = ArcRead(FileId,LocalPointer,SECTOR_SIZE,&Count)) != ESUCCESS) {
+ return Status;
+ }
+
+ PointerToExternalSymbols = ((PMIPS_SYMBOLIC_HEADER)LocalPointer)->PointerToExternalSymbols;
+ NumberOfExternalSymbols = ((PMIPS_SYMBOLIC_HEADER)LocalPointer)->NumOfExternalSymbols;
+
+
+ //
+ // Read the relocation table for each section.
+ //
+
+ MatchedReflo = FALSE;
+ for (Section=0; Section < R_SN_MAX; Section++) {
+ NumberOfRelocations = RelocationTable[Section].NumberOfRelocations;
+ for (Index = 0; Index < NumberOfRelocations; Index ++) {
+ if ((Index % (SECTOR_SIZE/sizeof(MIPS_RELOCATION_ENTRY))) == 0) {
+ //
+ // read a sector worth of relocation entries.
+ //
+ SeekPosition.LowPart = RelocationTable[Section].PointerToRelocations+Index*sizeof(MIPS_RELOCATION_ENTRY);
+ ArcSeek(FileId,
+ &SeekPosition,
+ SeekAbsolute);
+
+ Status = ArcRead(FileId,
+ LocalPointer,
+ SECTOR_SIZE,
+ &Count);
+ if (Status != ESUCCESS) {
+ return Status;
+ }
+ RelocationEntry = (PMIPS_RELOCATION_ENTRY)LocalPointer;
+ }
+
+ //
+ // Get the address for the fixup.
+ //
+
+ FixupAddress = (PULONG)(RelocationEntry->VirtualAddress +
+ RelocationTable[Section].FixupValue);
+ //
+ // Apply the fixup.
+ //
+
+ if (RelocationEntry->Type.External == 0) {
+
+ //
+ // If the relocation is internal, SymbolIndex
+ // supplies the number of the section containing the symbol.
+ // Compute the Offset for that section.
+ //
+
+ Offset = RelocationTable[RelocationEntry->Type.SymbolIndex].FixupValue;
+ } else {
+
+ // sprintf(Message,"External Relocation at:%lx\r\n",FixupAddress);
+ // VenPrint(Message);
+ //
+ // This is an external reference. Read the symbol table.
+ //
+
+ SeekPosition.LowPart = PointerToExternalSymbols+
+ RelocationEntry->Type.SymbolIndex*sizeof(MIPS_EXTERNAL_SYMBOL);
+ if ((Status =
+ ArcSeek(FileId,
+ &SeekPosition,
+ SeekAbsolute)) != ESUCCESS) {
+ return Status;
+ }
+
+ if ((Status = ArcRead(FileId,
+ &MipsExternalSymbol,
+ sizeof(MIPS_EXTERNAL_SYMBOL),
+ &Count)) != ESUCCESS) {
+ return Status;
+ }
+
+ //
+ // Check that the value of the symbol is an address.
+ //
+
+ Offset = MipsExternalSymbol.Symbol.Value;
+
+ if ((MipsExternalSymbol.Symbol.StorageClass == ESSC_TEXT) ||
+ (MipsExternalSymbol.Symbol.StorageClass == ESSC_DATA)) {
+ Offset+= RelocationTable[Section].FixupValue;
+ } else {
+ return EBADF;
+ }
+ }
+
+ switch (RelocationEntry->Type.Type) {
+
+ //
+ // Absolute - no fixup required.
+ //
+
+ case IMAGE_REL_MIPS_ABSOLUTE:
+ break;
+
+ //
+ // Word - (32-bits) relocate the entire address.
+ //
+
+ case IMAGE_REL_MIPS_REFWORD:
+
+ *FixupAddress += (ULONG)Offset;
+ break;
+
+ //
+ // Adjust high - (16-bits) relocate the high half of an
+ // address and adjust for sign extension of low half.
+ //
+
+ case IMAGE_REL_MIPS_JMPADDR:
+
+ FixupValue = ((*FixupAddress)&0x03fffff) + (Offset >> 2);
+ *FixupAddress = (*FixupAddress & 0xfc000000) | (FixupValue & 0x03fffff);
+ break;
+
+ case IMAGE_REL_MIPS_REFHI:
+
+ //
+ // Save the address and go to get REF_LO paired with this one
+ //
+
+ FixupAddressHi = (PUSHORT)FixupAddress;
+ MatchedReflo = TRUE;
+ break;
+
+ //
+ // Low - (16-bit) relocate high part too.
+ //
+
+ case IMAGE_REL_MIPS_REFLO:
+
+ if (MatchedReflo) {
+ FixupValue = (ULONG)(LONG)((*FixupAddressHi) << 16) +
+ *(PSHORT)FixupAddress +
+ Offset;
+
+ //
+ // Fix the High part
+ //
+
+ *FixupAddressHi = (SHORT)((FixupValue + 0x8000) >> 16);
+ MatchedReflo = FALSE;
+ } else {
+ FixupValue = *(PSHORT)FixupAddress + Offset;
+ }
+
+ //
+ // Fix the lower part.
+ //
+
+ *(PUSHORT)FixupAddress = (USHORT)(FixupValue & 0xffff);
+ break;
+
+ //
+ // Illegal - illegal relocation type.
+ //
+
+ default :
+ VenPrint(FW_UNKNOWN_RELOC_TYPE_MSG);
+ return EBADF;
+
+ }
+ RelocationEntry++;
+ }
+ }
+ return ESUCCESS;
+}
+
+//
+//ARC_STATUS
+//FwInvoke(
+// IN ULONG ExecAddr,
+// IN ULONG StackAddr,
+// IN ULONG Argc,
+// IN PCHAR Argv[],
+// IN PCHAR Envp[]
+// )
+//
+///*++
+//
+//Routine Description:
+//
+// This routine invokes a loaded program.
+//
+//Arguments:
+//
+// ExecAddr - Supplies the address of the routine to call.
+//
+// StackAddr - Supplies the address to which the stack pointer is set.
+//
+// Argc, Argv, Envp - Supply the arguments and endvironment to pass to
+// Loaded program.
+//
+//
+//Return Value:
+//
+// ESUCCESS is returned if the address is valid.
+// EFAULT indicates an invalid addres.
+//
+//--*/
+//
+//{
+// //
+// // Check for aligned address.
+// //
+// if ((ExecAddr & 0x3) == 0) {
+// ((PTRANSFER_ROUTINE)ExecAddr)(Argc, Argv, Envp);
+// return ESUCCESS;
+// } else {
+// return EFAULT;
+// }
+//}
+
+
+VOID
+FwCopyArguments(
+ IN ULONG Argc,
+ IN PCHAR Argv[]
+ )
+
+/*++
+
+Routine Description:
+
+ This routine copies the supplied arguments into the Fw
+ space.
+
+Arguments:
+
+ Argc, Argv, - Supply the arguments to be copied.
+
+
+Return Value:
+
+ ESUCCESS is returned if the arguments were successfully copied.
+ EFAULT if there is not enough room for them.
+
+--*/
+
+{
+ PUCHAR Source,Destination;
+ ULONG Arg;
+
+ PSavedArgs->Argc = Argc;
+ Destination = &PSavedArgs->Arguments[0];
+ for (Arg = 0; Arg < Argc; Arg++) {
+ Source = Argv[Arg];
+ PSavedArgs->Argv[Arg] = Destination;
+ while(*Destination++ = *Source++) {
+ }
+ }
+}
+
+
+ARC_STATUS
+FwPrivateExecute(
+ IN PCHAR Path,
+ IN ULONG Argc,
+ IN PCHAR Argv[],
+ IN PCHAR Envp[]
+ )
+
+/*++
+
+Routine Description:
+
+ This routine loads and invokes a program.
+ FwExecute sets the right stack pointer and calls this routine which
+ does all the work. When this routine returns (after the loaded
+ program has been executed) the stack is restored to the Fw stack
+ and control is returned to the firmware.
+ Therefore a loaded program that executes another program does not
+ get control back once the executed program is finished.
+
+Arguments:
+
+ Path - Supplies a pointer to the path of the file to load.
+
+ Argc, Argv, Envp - Supply the arguments and environment to pass to
+ Loaded program.
+
+
+Return Value:
+
+ ESUCCESS is returned if the address is valid.
+ EFAULT indicates an invalid addres.
+
+--*/
+
+{
+
+ PULONG TransferRoutine;
+ ULONG BottomAddress;
+ ARC_STATUS Status;
+ PMEMORY_DESCRIPTOR MemoryDescriptor;
+ PFW_MEMORY_DESCRIPTOR FwMemoryDescriptor;
+ CHAR TempPath[256];
+
+ //
+ // Copy the Arguments to a safe place as they can be in the
+ // running program space which can be overwritten by the program
+ // about to be loaded.
+ //
+ FwCopyArguments(Argc,Argv);
+ strcpy(TempPath, Path);
+
+ //
+ // Reinitialize the memory descriptors
+ //
+ FwResetMemory();
+
+ //
+ // Look for a piece of free memory.
+ //
+ MemoryDescriptor = ArcGetMemoryDescriptor(NULL);
+ while (MemoryDescriptor != NULL){
+
+ //
+ // If the memory is at least 4 megabytes and is free attempt to
+ // load the program.
+ //
+
+#ifdef ALPHA
+ if ((MemoryDescriptor->MemoryType == MemoryFree) &&
+ (MemoryDescriptor->PageCount >= FOUR_MB_PAGECOUNT)) {
+#else
+ if ((MemoryDescriptor->MemoryType == MemoryFree) &&
+ (MemoryDescriptor->PageCount >= 1024)) {
+#endif
+
+ //
+ // Set the top address to the top of the descriptor.
+ //
+
+ Status = FwLoad(TempPath,
+ ((MemoryDescriptor->BasePage +
+ MemoryDescriptor->PageCount) << PAGE_SHIFT) | KSEG0_BASE,
+ (PULONG)&TransferRoutine,
+ &BottomAddress);
+
+ if (Status == ESUCCESS) {
+
+ //
+ // Find the actual area of memory that was used, and generate a
+ // descriptor for it.
+ //
+
+ MemoryDescriptor = ArcGetMemoryDescriptor(NULL);
+ while (MemoryDescriptor != NULL){
+ if ((MemoryDescriptor->MemoryType == MemoryFree) &&
+ (FwActualBasePage >= MemoryDescriptor->BasePage) &&
+ ((FwActualBasePage + FwPageCount) <=
+ (MemoryDescriptor->BasePage + MemoryDescriptor->PageCount))) {
+ break;
+ }
+
+ MemoryDescriptor = ArcGetMemoryDescriptor(MemoryDescriptor);
+ }
+
+ if (MemoryDescriptor != NULL) {
+ FwMemoryDescriptor = CONTAINING_RECORD(MemoryDescriptor,
+ FW_MEMORY_DESCRIPTOR,
+ MemoryEntry);
+
+ FwGenerateDescriptor(FwMemoryDescriptor,
+ MemoryLoadedProgram,
+ FwActualBasePage,
+ FwPageCount);
+ }
+
+#ifdef ALPHA_FW_KDHOOKS
+ if (BreakAfterLoad == TRUE) {
+ DbgBreakPoint();
+ }
+#endif
+
+ AlphaInstIMB();
+ return FwInvoke((ULONG)TransferRoutine,
+ BottomAddress,
+ PSavedArgs->Argc,
+ PSavedArgs->Argv,
+ Envp
+ );
+ }
+
+ if (Status != ENOMEM) {
+ return Status;
+ }
+ }
+ MemoryDescriptor = ArcGetMemoryDescriptor(MemoryDescriptor);
+ }
+ return ENOMEM;
+}
+
+VOID
+FwLoadInitialize(
+ IN VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the firmware load services.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ (PARC_LOAD_ROUTINE)SYSTEM_BLOCK->FirmwareVector[LoadRoutine] = FwLoad;
+ (PARC_INVOKE_ROUTINE)SYSTEM_BLOCK->FirmwareVector[InvokeRoutine] = FwInvoke;
+ (PARC_EXECUTE_ROUTINE)SYSTEM_BLOCK->FirmwareVector[ExecuteRoutine] = FwExecute;
+ FwTemporaryStack = (ULONG) FwAllocatePool(0x3000) + 0x3000;
+ PSavedArgs = (PSAVED_ARGUMENTS) FwAllocatePool(sizeof(SAVED_ARGUMENTS));
+}
diff --git a/private/ntos/fw/alpha/fwmemdef.h b/private/ntos/fw/alpha/fwmemdef.h
new file mode 100644
index 000000000..f20701661
--- /dev/null
+++ b/private/ntos/fw/alpha/fwmemdef.h
@@ -0,0 +1,101 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ fwmemdef.h
+
+Abstract:
+
+ This module contains firmware memory space definitions used to
+ configure the memory descriptors and initialize memory. They are
+ all physical (non-KSEG0_BASE) addresses. See
+ \nt\private\ntos\fw\alpha\jxmemory.c for more information.
+
+Author:
+
+ John DeRosa [DEC] 26-Jan-1993
+
+Revision History:
+
+--*/
+
+#ifndef _FWMEMDEF_
+#define _FWMEMDEF_
+
+
+//
+// The byte address of the first byte beyond the firmware
+// SYSTEM_BLOCK, PALcode, code, data, and stack.
+//
+
+#ifdef JENSEN
+#define FW_TOP_ADDRESS 0x770000
+#else
+#define FW_TOP_ADDRESS 0x780000
+#endif
+
+//
+// The byte address of the lowest byte in the firmware stack. This
+// is used by the firmware RtlCheckStack to check for stack underflow.
+//
+
+#define FW_STACK_SIZE 0x10000
+#define FW_STACK_LOWER_BOUND (FW_TOP_ADDRESS - FW_STACK_SIZE)
+
+//
+// The byte address of the base of the firmware SYSTEM_BLOCK, PALcode, code,
+// data, and stack.
+//
+
+#define FW_BOTTOM_ADDRESS 0x6FE000
+
+//
+// The size of the firmware SYSTEM_BLOCK, PALcode, code, data, and stack,
+// in pages.
+//
+
+#define FW_PAGES ( (FW_TOP_ADDRESS - FW_BOTTOM_ADDRESS) >> PAGE_SHIFT )
+
+//
+// Byte address and size of the firwmare pool.
+// It is located directly after the PALcode, code, and stack.
+//
+// It is 128KB. On Mips it was only 64KB, and the Alpha firmware ran with
+// 64KB for a long time. But an easy fix for a bug in EISA I/O on 64MB
+// Jensens is to double the pool size.
+//
+// ** Because of the way that the memory descriptors work, the size
+// ** must be an even multiple of the page size.
+//
+
+#define FW_POOL_BASE FW_TOP_ADDRESS
+#define FW_POOL_SIZE 0x20000
+
+//
+// Byte address of the first location after the firmware pool. From here
+// to the end of memory is initialized as MemoryFree by the firwmare.
+//
+
+#define FW_BASE_REMAINDER_MEMORY ( FW_POOL_BASE + FW_POOL_SIZE )
+
+
+//
+// Convenient numbers.
+//
+
+#define SIXTY_FOUR_KB 0x010000
+#define _512_KB 0x080000
+#define ONE_MB 0x100000
+#define FOUR_MB 0x400000
+#define FOUR_MB_PAGECOUNT ( FOUR_MB >> PAGE_SHIFT )
+#define SEVEN_MB 0x700000
+#define EIGHT_MB 0x800000
+#define NINE_MB 0x900000
+#define SIXTEEN_MB 0x1000000
+#define THIRTY_ONE_MB 0x1f00000
+#define THIRTY_TWO_MB 0x2000000
+
+
+#endif // _FWMEMDEF_
diff --git a/private/ntos/fw/alpha/fwp.h b/private/ntos/fw/alpha/fwp.h
new file mode 100644
index 000000000..b88171557
--- /dev/null
+++ b/private/ntos/fw/alpha/fwp.h
@@ -0,0 +1,720 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ fwp.h
+
+Abstract:
+
+ This module contains extensions to the firmware.h and alpharefs.h files.
+
+ N.B. This is *not* a private file. Although "p" versions of
+ .h files are normally private in the source pool, fwp.h is included
+ by other builds.
+
+ This version is for use at Microsoft, to enable bldr files to
+ build correctly. (scsiboot.c, scsidisk.c)
+
+Author:
+
+ David M. Robinson (davidro) 29-Aug-1991
+
+Revision History:
+
+ 15-April-1992 John DeRosa [DEC]
+
+ Modified for Alpha.
+
+--*/
+
+#ifndef _FWP_
+#define _FWP_
+
+
+#include "bldr.h"
+#include "firmware.h"
+#include "iodevice.h"
+#include "vendor.h"
+#include "debug.h"
+#include "fwcallbk.h"
+
+//
+// Current version and revision numbers.
+//
+
+#define ARC_VERSION 1
+#define ARC_REVISION 2
+
+//
+// In the running system, this is held in the PCR. We hardcode it
+// for Alpha/Jensen Firmware.
+//
+
+#undef KeGetDcacheFillSize
+#define KeGetDcacheFillSize() 32L
+
+
+//
+// Needed by conftest.c, jxboot,c jnsetcfg.c
+//
+
+#define MAXIMUM_DEVICE_SPECIFIC_DATA 32
+
+
+
+//
+// Define the ROM types supported by this code package.
+//
+
+typedef enum _ROM_TYPE {
+ I28F008SA,
+ Am29F010,
+ InvalidROM
+} ROM_TYPE, *PROM_TYPE;
+
+//
+// Masks used by FwSystemConsistencyCheck for returning machine state.
+//
+// These are divided into "red" and "yellow" problems. Red problems
+// will prevent the system from booting properly. Yellow problems may
+// or may not prevent the system from booting properly.
+//
+// The order of the red and yellow problem bits must match the
+// order of SetupMenuChoices[] and MachineProblemAreas[]. This
+// makes the bit-shifting and bit-peeling easier in jnsetset.c
+// and jxboot.c.
+//
+// Firmware code assumes that the right 16 bits are red problems, and the
+// left 16 bits are yellow problems.
+//
+
+#define FWP_MACHINE_PROBLEMS_NOPROBLEMS 0 // No problems
+
+ //
+ // Red problems.
+ //
+ // These will, in all likelyhood, prevent a good boot.
+ // If these are set, we will not allow an NT installation.
+ // If any of these besides the ECU bit are set, we will not auto-run the ECU.
+ //
+
+#define FWP_MACHINE_PROBLEMS_TIME 0x01 // System time
+#define FWP_MACHINE_PROBLEMS_EV 0x02 // Environment variables
+#define FWP_MACHINE_PROBLEMS_CDS 0x04 // CDS tree
+#define FWP_MACHINE_PROBLEMS_MPRESERVEDBOOT 0x08 // Reserved
+#define FWP_MACHINE_PROBLEMS_MPRESERVEDR1 0x10 // Unused
+#define FWP_MACHINE_PROBLEMS_MPRESERVEDR2 0x20 // Unused
+#define FWP_MACHINE_PROBLEMS_ECU 0x40 // EISA config. data
+
+#define FWP_MACHINE_PROBLEMS_RED 0xffff // Some Red bit is set
+
+ //
+ // Yellow problems.
+ //
+ // These may not cause any difficulty in booting.
+ // We will allow NT to be installed even if these are set.
+ // We will auto-run the ECU even if any of these are set.
+ //
+
+#define FWP_MACHINE_PROBLEMS_MPRESERVEDTIME 0x010000 // Reserved
+#define FWP_MACHINE_PROBLEMS_MPRESERVEDEV 0x020000 // Reserved
+#define FWP_MACHINE_PROBLEMS_MPRESERVEDCDS 0x040000 // Reserved
+#define FWP_MACHINE_PROBLEMS_BOOT 0x080000 // Boot selections
+#define FWP_MACHINE_PROBLEMS_MPRESERVEDY1 0x100000 // Unused
+#define FWP_MACHINE_PROBLEMS_MPRESERVEDY2 0x200000 // Unused
+#define FWP_MACHINE_PROBLEMS_MPRESERVEDECU 0x400000 // Reserved
+
+#define FWP_MACHINE_PROBLEMS_YELLOW 0xffff0000 // Some Yellow bit is set
+
+
+//
+// These control FwSystemConsistencyCheck.
+//
+
+#define FWSCC_STALL_RETURN 0
+#define FWSCC_KEY_INPUT_THEN_RETURN 1
+
+
+//
+// Define the Lookup table. At initialization, the driver must fill this table
+// with the device pathnames it can handle.
+//
+
+typedef struct _DRIVER_LOOKUP_ENTRY {
+ PCHAR DevicePath;
+ PBL_DEVICE_ENTRY_TABLE DispatchTable;
+} DRIVER_LOOKUP_ENTRY, *PDRIVER_LOOKUP_ENTRY;
+
+#define SIZE_OF_LOOKUP_TABLE BL_FILE_TABLE_SIZE
+
+extern DRIVER_LOOKUP_ENTRY DeviceLookupTable[SIZE_OF_LOOKUP_TABLE];
+
+//
+// Define the Device Pathname. This table is indexed with the FileId.
+// FwOpen tries to match the OpenPath with the entries in this table, and
+// if it finds a match it increments the reference counter. If it doesn't
+// find a match it tries to match an entry in the DRIVER_LOOKUP_TABLE
+// and then calls the Open routine of that driver.
+//
+
+#define SIZE_OF_ARC_DEVICENAME 64
+
+typedef struct _OPENED_PATHNAME_ENTRY {
+ ULONG ReferenceCounter;
+ CHAR DeviceName[SIZE_OF_ARC_DEVICENAME];
+} OPENED_PATHNAME_ENTRY, *POPENED_PATHNAME_ENTRY;
+
+#define SIZE_OF_OPENED_PATHNAME_TABLE BL_FILE_TABLE_SIZE
+
+extern OPENED_PATHNAME_ENTRY OpenedPathTable[SIZE_OF_OPENED_PATHNAME_TABLE];
+
+//
+// Driver initialization routines.
+//
+
+VOID
+FwOpenConsole(
+ IN VOID
+ );
+
+VOID
+FwInitializeMemory(
+ IN VOID
+ );
+
+VOID
+FwResetMemory(
+ IN VOID
+ );
+
+VOID
+DisplayInitialize(
+ IN OUT PDRIVER_LOOKUP_ENTRY LookupTableEntry,
+ IN ULONG Entries
+ );
+
+VOID
+KeyboardInitialize(
+ IN OUT PDRIVER_LOOKUP_ENTRY LookupTableEntry,
+ IN ULONG Entries
+ );
+
+VOID
+SerialInitialize(
+ IN OUT PDRIVER_LOOKUP_ENTRY LookupTableEntry,
+ IN ULONG Entries
+ );
+
+typedef
+VOID
+(*PSCSI_INFO_CALLBACK_ROUTINE) (
+ IN ULONG AdapterNumber,
+ IN ULONG ScsiId,
+ IN ULONG Lun,
+ IN BOOLEAN Cdrom
+ );
+
+#define SCSI_INFO_CALLBACK_DEFINED 1
+
+VOID
+HardDiskInitialize(
+ IN OUT PDRIVER_LOOKUP_ENTRY LookupTable,
+ IN ULONG Entries,
+ IN PSCSI_INFO_CALLBACK_ROUTINE DeviceFound
+ );
+
+VOID
+FloppyInitialize(
+ IN OUT PDRIVER_LOOKUP_ENTRY LookupTableEntry,
+ IN ULONG Entries
+ );
+
+
+//
+// Platforms with true NVRAM for the ARC data area uses different code
+// than the platforms that store the data in a Flash ROM.
+//
+// Platforms using NVRAM:
+//
+// Morgan
+// eb66
+// e64p
+// Mustang
+//
+// Platforms using Flash ROM:
+//
+// Jensen
+// Culzean
+//
+
+#if defined(NV_RAM_PLATFORM)
+
+#define FwROMSetARCDataToReadMode()
+#define FwROMResetStatus(x)
+
+#elif defined(FLASH_ROM_PLATFORM)
+
+//
+// Flash ROM machines
+//
+
+ARC_STATUS
+FwROMByteWrite(
+ IN PUCHAR WriteAddress,
+ IN UCHAR WriteData
+ );
+
+VOID
+FwROMSetARCDataToReadMode (
+ VOID
+ );
+
+VOID
+FwROMResetStatus(
+ IN PUCHAR Address
+ );
+
+#endif
+
+extern ULONG IdentifierIndex;
+extern ULONG DataIndex;
+extern ULONG EisaDataIndex;
+//extern PCONFIGURATION Configuration;
+
+extern PUCHAR VolatileEnvironment;
+
+extern ULONG MemorySize;
+
+//
+// Define special character values. TEMPTEMP These should go somewhere else.
+//
+
+#define ASCII_NUL 0x00
+#define ASCII_BEL 0x07
+#define ASCII_BS 0x08
+#define ASCII_HT 0x09
+#define ASCII_LF 0x0A
+#define ASCII_VT 0x0B
+#define ASCII_FF 0x0C
+#define ASCII_CR 0x0D
+#define ASCII_CSI 0x9B
+#define ASCII_ESC 0x1B
+#define ASCII_SYSRQ 0x80
+
+//
+// Define screen colors.
+//
+
+typedef enum _ARC_SCREEN_COLOR {
+ ArcColorBlack,
+ ArcColorRed,
+ ArcColorGreen,
+ ArcColorYellow,
+ ArcColorBlue,
+ ArcColorMagenta,
+ ArcColorCyan,
+ ArcColorWhite,
+ MaximumArcColor
+ } ARC_SCREEN_COLOR;
+
+
+//
+// Define firmware routine prototypes.
+//
+
+PVOID
+FwAllocatePool (
+ IN ULONG NumberOfBytes
+ );
+
+VOID
+FwStallExecution (
+ IN ULONG Microseconds
+ );
+
+ULONG
+FwPrint (
+ IN PCHAR Format,
+ ...
+ );
+
+VOID
+FwReturnExtendedSystemInformation (
+ OUT PEXTENDED_SYSTEM_INFORMATION SystemInfo
+ );
+
+ARC_STATUS
+DisplayBootInitialize (
+ OUT PVOID UnusedParameter
+ );
+
+ULONG
+EISAReadRegisterBufferUCHAR (
+ IN ULONG BusNumber,
+ IN ULONG Offset,
+ OUT PVOID Buffer,
+ IN ULONG Length
+ );
+
+ULONG
+EISAWriteRegisterBufferUCHAR (
+ IN ULONG BusNumber,
+ IN ULONG Offset,
+ OUT PVOID Buffer,
+ IN ULONG Length
+ );
+
+UCHAR
+EISAReadPortUCHAR (
+ IN ULONG BusNumber,
+ IN ULONG Offset
+ );
+
+USHORT
+EISAReadPortUSHORT (
+ IN ULONG BusNumber,
+ IN ULONG Offset
+ );
+
+ULONG
+EISAReadPortULONG (
+ IN ULONG BusNumber,
+ IN ULONG Offset
+ );
+
+VOID
+EISAWritePortUCHAR (
+ IN ULONG BusNumber,
+ IN ULONG Offset,
+ IN UCHAR Datum
+ );
+
+VOID
+EISAWritePortUSHORT (
+ IN ULONG BusNumber,
+ IN ULONG Offset,
+ IN USHORT Datum
+ );
+
+VOID
+EISAWritePortULONG (
+ IN ULONG BusNumber,
+ IN ULONG Offset,
+ IN ULONG Datum
+ );
+
+USHORT
+EISAReadPortUSHORT (
+ IN ULONG BusNumber,
+ IN ULONG Offset
+ );
+
+VOID
+FwDriverEntry (
+ IN PVOID DriverObject,
+ IN PVOID Argument2
+ );
+
+VOID
+FwIoInitialize1 (
+ VOID
+ );
+
+VOID
+FwIoInitialize2 (
+ VOID
+ );
+
+BOOLEAN
+JzGetPathMnemonicKey(
+ IN PCHAR OpenPath,
+ IN PCHAR Mnemonic,
+ OUT PULONG Key
+ );
+#define FwGetPathMnemonicKey JzGetPathMnemonicKey // For bldr\scsidisk.c
+
+PCHAR
+FwEnvironmentLoad(
+ VOID
+ );
+
+PCHAR
+FwGetVolatileEnvironmentVariable (
+ IN PCHAR Variable
+ );
+
+ARC_STATUS
+FwROMDetermineMachineROMType (
+ VOID
+ );
+
+VOID
+FwROMSetReadMode(
+ IN PUCHAR Address
+ );
+
+ARC_STATUS
+FwROMErase64KB(
+ IN PUCHAR EraseAddress
+ );
+
+ARC_STATUS
+FwCoreSetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN PCHAR Value,
+ IN BOOLEAN UpdateTheRom
+ );
+
+VOID
+ParseARCErrorStatus(
+ IN ARC_STATUS Status
+ );
+
+BOOLEAN
+JzMakeDefaultConfiguration (
+ IN BOOLEAN DoFactoryDefaults
+ );
+
+VOID
+FwSystemConsistencyCheck (
+ IN BOOLEAN Silent,
+ IN PCHAR BottomMessage,
+ IN ULONG BottomMethod,
+ OUT PULONG Problems
+ );
+
+VOID
+JzCheckBootSelections (
+ IN BOOLEAN Silent,
+ OUT PBOOLEAN FoundProblems
+ );
+
+BOOLEAN
+JzMakeDefaultEnvironment (
+ IN BOOLEAN DoFactoryDefaults
+ );
+
+VOID
+JzDisplayOtherEnvironmentVariables (
+ VOID
+ );
+
+VOID
+HalpWriteVti(
+ IN ULONG RTCIndex,
+ IN UCHAR Data
+ );
+
+UCHAR
+HalpReadVti(
+ IN ULONG RTCIndex
+ );
+
+ARC_STATUS
+DisplayBootInitialize(
+ PVOID UnusedParameter
+ );
+
+ARC_STATUS
+FwGetVideoData (
+ OUT PMONITOR_CONFIGURATION_DATA MonitorData
+ );
+
+VOID
+FwTerminationInitialize(
+ IN VOID
+ );
+
+VOID
+FwHalt(
+ IN VOID
+ );
+
+VOID
+FwMonitor(
+ IN ULONG
+ );
+
+VOID
+FwExceptionInitialize(
+ IN VOID
+ );
+
+VOID
+ResetSystem (
+ IN VOID
+ );
+
+
+VOID
+FwpFreeStub(
+ IN PVOID Buffer
+ );
+
+typedef enum _GETSTRING_ACTION {
+ GetStringSuccess,
+ GetStringEscape,
+ GetStringUpArrow,
+ GetStringDownArrow,
+ GetStringMaximum
+} GETSTRING_ACTION, *PGETSTRING_ACTION;
+
+GETSTRING_ACTION
+JzGetString(
+ OUT PCHAR String,
+ IN ULONG StringLength,
+ IN PCHAR InitialString OPTIONAL,
+ IN ULONG CurrentRow,
+ IN ULONG CurrentColumn,
+ IN BOOLEAN ShowTheTime
+ );
+
+ULONG
+JzDisplayMenu (
+ IN PCHAR Choices[],
+ IN ULONG NumberOfChoices,
+ IN LONG DefaultChoice,
+ IN ULONG CurrentLine,
+ IN LONG AutobootValue,
+ IN BOOLEAN ShowTheTime
+ );
+
+ARC_STATUS
+FwConfigurationCheckChecksum (
+ VOID
+ );
+
+ARC_STATUS
+JzEnvironmentCheckChecksum (
+ VOID
+ );
+
+VOID
+FwpReservedRoutine(
+ VOID
+ );
+
+ARC_STATUS
+SerialBootWrite(
+ CHAR Char,
+ ULONG SP
+ );
+
+VOID
+FirmwareSetupProgram(
+ OUT PBOOLEAN RunProgram,
+ OUT PCHAR PathName
+ );
+
+
+//
+// This macro should be used when adding a descriptor to the memory
+// descriptor list.
+//
+
+#define INCREMENT_FWMEMORYFREE \
+ if (FwMemoryFree == (FW_MEMORY_TABLE_SIZE - 1)) { \
+ KeBugCheck(ENOMEM); \
+ } else { \
+ FwMemoryFree++; \
+ }
+
+//
+// Print macros.
+//
+
+extern BOOLEAN DisplayOutput;
+extern BOOLEAN SerialOutput;
+extern BOOLEAN FwConsoleInitialized;
+extern ULONG DisplayWidth;
+
+
+//
+// Fw____ screen manipulation macros.
+//
+
+#define FwClearScreen() \
+ FwPrint("%c2J", ASCII_CSI)
+
+#define FwMoveCursorToColumn(Spaces) \
+ FwPrint("\r\x9B"#Spaces"C")
+
+#define FwSetScreenColor(FgColor, BgColor) \
+ FwPrint("%c3%dm", ASCII_CSI, (UCHAR)FgColor); \
+ FwPrint("%c4%dm", ASCII_CSI, (UCHAR)BgColor)
+
+#define FwSetScreenAttributes( HighIntensity, Underscored, ReverseVideo ) \
+ FwPrint("%c0m", ASCII_CSI); \
+ if (HighIntensity) { \
+ FwPrint("%c1m", ASCII_CSI); \
+ } \
+ if (Underscored) { \
+ FwPrint("%c4m", ASCII_CSI); \
+ } \
+ if (ReverseVideo) { \
+ FwPrint("%c7m", ASCII_CSI); \
+ }
+
+#define FwSetPosition( Row, Column ) \
+ FwPrint("%c%d;", ASCII_CSI, Row); \
+ FwPrint("%dH", Column)
+
+
+
+
+//
+// Error printing macro for the EISA configuration code. The global
+// that is set to TRUE will cause execution to stall so that the user
+// can see the error messages.
+//
+
+extern BOOLEAN ErrorsDuringEISABusConfiguration;
+
+#define EISAErrorFwPrint(x) FwPrint(x); \
+ ErrorsDuringEISABusConfiguration = TRUE;
+#define EISAErrorFwPrint1(x,y) FwPrint(x,y); \
+ ErrorsDuringEISABusConfiguration = TRUE;
+#define EISAErrorFwPrint2(x,y,z) FwPrint(x,y,z); \
+ ErrorsDuringEISABusConfiguration = TRUE;
+
+
+//
+// Definitions for the setup program
+//
+
+extern PCHAR BootString[];
+
+extern BOOLEAN SetupROMPendingModified;
+
+typedef enum _BOOT_VARIABLES {
+ LoadIdentifierVariable,
+ SystemPartitionVariable,
+ OsLoaderVariable,
+ OsLoadPartitionVariable,
+ OsLoadFilenameVariable,
+ OsLoadOptionsVariable,
+ MaximumBootVariable
+ } BOOT_VARIABLE;
+
+
+//
+// Convenient numbers.
+//
+
+#define SIXTY_FOUR_KB 0x010000
+#define _512_KB 0x080000
+#define ONE_MB 0x100000
+#define FOUR_MB 0x400000
+#define FOUR_MB_PAGECOUNT ( FOUR_MB >> PAGE_SHIFT )
+#define SEVEN_MB 0x700000
+#define EIGHT_MB 0x800000
+#define NINE_MB 0x900000
+#define SIXTEEN_MB 0x1000000
+#define THIRTY_ONE_MB 0x1f00000
+#define THIRTY_TWO_MB 0x2000000
+
+
+#endif // _FWP_
diff --git a/private/ntos/fw/alpha/fwpexcpt.h b/private/ntos/fw/alpha/fwpexcpt.h
new file mode 100644
index 000000000..e888da2ae
--- /dev/null
+++ b/private/ntos/fw/alpha/fwpexcpt.h
@@ -0,0 +1,148 @@
+/*++
+
+ fwpexcpt.h
+
+ Copyright (C) 1993 Digital Equipment Corporation
+
+
+ Description:
+ fw (firmware) pal code exception frame definitions
+ fw (firmware) pal code specific definitions
+
+ Author:
+ Joe Notarangelo 18-Jun-1992
+
+ Revisions:
+ Bruce Butts 14-Apr-1993
+
+ Removed definitions of FW_INITIAL_SP and FW_SP_LOW_LIMIT.
+ Firmware memory map defined in ntos\fw\alpha\fwmemdef.h
+
+--*/
+
+//
+// Firmware processor information definition
+//
+
+typedef struct _FW_PROCESSOR_INFORMATION{
+ ULONG ProcessorId;
+ ULONG ProcessorRevision;
+ ULONG PhysicalAddressBits;
+ ULONG MaximumAddressSpaceNumber;
+ ULONG PageSize;
+} FW_PROCESSOR_INFORMATION, *PFW_PROCESSOR_INFORMATION;
+
+//
+// Firmware system information definition
+//
+
+typedef struct _FW_SYSTEM_INFORMATION{
+ ULONG MemorySizeInBytes;
+ ULONG SystemRevisionId;
+ ULONG SystemCycleClockPeriod;
+ ULONG Unused; // Was the restart address field.
+} FW_SYSTEM_INFORMATION, *PFW_SYSTEM_INFORMATION;
+
+//
+// Firmware exception type definitions
+//
+#define FW_EXC_MCHK 0xdec0
+#define FW_EXC_ARITH 0xdec1
+#define FW_EXC_INTERRUPT 0xdec2
+#define FW_EXC_DFAULT 0xdec3
+#define FW_EXC_ITBMISS 0xdec4
+#define FW_EXC_ITBACV 0xdec5
+#define FW_EXC_NDTBMISS 0xdec6
+#define FW_EXC_PDTBMISS 0xdec7
+#define FW_EXC_UNALIGNED 0xdec8
+#define FW_EXC_OPCDEC 0xdec9
+#define FW_EXC_FEN 0xdeca
+#define FW_EXC_HALT 0xdecb
+#define FW_EXC_BPT 0xdecc
+#define FW_EXC_GENTRAP 0xdecd
+
+#define FW_EXC_FIRST FW_EXC_MCHK
+#define FW_EXC_LAST FW_EXC_GENTRAP
+
+
+//
+// Firmware exception frame definition
+//
+
+typedef struct _FW_EXCEPTION_FRAME {
+ ULONG ExceptionType;
+ ULONG Filler;
+ ULONGLONG ExceptionParameter1;
+ ULONGLONG ExceptionParameter2;
+ ULONGLONG ExceptionParameter3;
+ ULONGLONG ExceptionParameter4;
+ ULONGLONG ExceptionParameter5;
+ ULONGLONG ExceptionProcessorStatus;
+ ULONGLONG ExceptionMmCsr;
+ ULONGLONG ExceptionVa;
+ ULONGLONG ExceptionFaultingInstructionAddress;
+ ULONGLONG ExceptionV0;
+ ULONGLONG ExceptionT0;
+ ULONGLONG ExceptionT1;
+ ULONGLONG ExceptionT2;
+ ULONGLONG ExceptionT3;
+ ULONGLONG ExceptionT4;
+ ULONGLONG ExceptionT5;
+ ULONGLONG ExceptionT6;
+ ULONGLONG ExceptionT7;
+ ULONGLONG ExceptionS0;
+ ULONGLONG ExceptionS1;
+ ULONGLONG ExceptionS2;
+ ULONGLONG ExceptionS3;
+ ULONGLONG ExceptionS4;
+ ULONGLONG ExceptionS5;
+ ULONGLONG ExceptionFp;
+ ULONGLONG ExceptionA0;
+ ULONGLONG ExceptionA1;
+ ULONGLONG ExceptionA2;
+ ULONGLONG ExceptionA3;
+ ULONGLONG ExceptionA4;
+ ULONGLONG ExceptionA5;
+ ULONGLONG ExceptionT8;
+ ULONGLONG ExceptionT9;
+ ULONGLONG ExceptionT10;
+ ULONGLONG ExceptionT11;
+ ULONGLONG ExceptionRa;
+ ULONGLONG ExceptionT12;
+ ULONGLONG ExceptionAt;
+ ULONGLONG ExceptionGp;
+ ULONGLONG ExceptionSp;
+ ULONGLONG ExceptionZero;
+ ULONGLONG ExceptionF0;
+ ULONGLONG ExceptionF1;
+ ULONGLONG ExceptionF2;
+ ULONGLONG ExceptionF3;
+ ULONGLONG ExceptionF4;
+ ULONGLONG ExceptionF5;
+ ULONGLONG ExceptionF6;
+ ULONGLONG ExceptionF7;
+ ULONGLONG ExceptionF8;
+ ULONGLONG ExceptionF9;
+ ULONGLONG ExceptionF10;
+ ULONGLONG ExceptionF11;
+ ULONGLONG ExceptionF12;
+ ULONGLONG ExceptionF13;
+ ULONGLONG ExceptionF14;
+ ULONGLONG ExceptionF15;
+ ULONGLONG ExceptionF16;
+ ULONGLONG ExceptionF17;
+ ULONGLONG ExceptionF18;
+ ULONGLONG ExceptionF19;
+ ULONGLONG ExceptionF20;
+ ULONGLONG ExceptionF21;
+ ULONGLONG ExceptionF22;
+ ULONGLONG ExceptionF23;
+ ULONGLONG ExceptionF24;
+ ULONGLONG ExceptionF25;
+ ULONGLONG ExceptionF26;
+ ULONGLONG ExceptionF27;
+ ULONGLONG ExceptionF28;
+ ULONGLONG ExceptionF29;
+ ULONGLONG ExceptionF30;
+ ULONGLONG ExceptionF31;
+} FW_EXCEPTION_FRAME, *PFW_EXCEPTION_FRAME;
diff --git a/private/ntos/fw/alpha/fwprint.c b/private/ntos/fw/alpha/fwprint.c
new file mode 100644
index 000000000..c6803cdcf
--- /dev/null
+++ b/private/ntos/fw/alpha/fwprint.c
@@ -0,0 +1,138 @@
+// TITLE("Debug Support Functions")
+//++
+//
+// Copyright (c) 1990 Microsoft Corporation
+// Copyright (c) 1993 Digital Equipment Corporation
+//
+// Module Name:
+//
+// fwprint.c
+//
+// Abstract:
+//
+// This module implements functions to support debugging NT.
+//
+// Author:
+//
+// Steven R. Wood (stevewo) 3-Aug-1989
+//
+// Environment:
+//
+// Any mode.
+//
+// Revision History:
+//
+// 18-Dec-1992 John DeRosa [DEC]
+//
+// Added Alpha_AXP/Jensen modifications.
+//--
+
+#include "fwp.h"
+#include <stdarg.h>
+#include "string.h"
+
+
+//
+// Define variable argument list parameters.
+//
+
+BOOLEAN DisplayOutput;
+BOOLEAN SerialOutput;
+BOOLEAN FwConsoleInitialized;
+
+
+
+//
+// Debug support, to let us direct printfs to the serial line.
+//
+
+#ifdef ALPHA_FW_SERDEB
+
+
+//
+// If this is TRUE, SerFwPrint will output to the serial line.
+// If this is FALSE, SerFwPrint will return without printing anything.
+// This lets me insert SerFwPrint into low-level functions, and enable
+// diagnostic output in a high-level caller.
+//
+
+BOOLEAN SerSnapshot;
+
+
+ULONG
+SerFwPrint (
+ PCHAR Format,
+ ...
+ )
+
+{
+
+ va_list arglist;
+ UCHAR Buffer[256];
+ ULONG Count;
+ ULONG Index;
+ ULONG Length;
+
+ if (SerSnapshot) {
+
+ //
+ // Format the output into a buffer and then print it.
+ //
+
+ va_start(arglist, Format);
+ Length = vsprintf(Buffer, Format, arglist);
+
+ for ( Index = 0 ; Index < Length ; Index++ ) {
+ SerialBootWrite(Buffer[Index], COMPORT1_VIRTUAL_BASE);
+ }
+
+ va_end(arglist);
+ }
+
+ return 0;
+}
+
+#endif
+
+
+ULONG
+FwPrint (
+ PCHAR Format,
+ ...
+ )
+
+{
+
+ va_list arglist;
+ UCHAR Buffer[256];
+ ULONG Count;
+ ULONG Index;
+ ULONG Length;
+
+ //
+ // Format the output into a buffer and then print it.
+ //
+
+ va_start(arglist, Format);
+ Length = vsprintf(Buffer, Format, arglist);
+
+ if (FwConsoleInitialized) {
+
+ FwWrite( ARC_CONSOLE_OUTPUT, Buffer, Length, &Count);
+
+ } else {
+
+ if (SerialOutput) {
+ for ( Index = 0 ; Index < Length ; Index++ ) {
+ SerialBootWrite(Buffer[Index],COMPORT1_VIRTUAL_BASE);
+ }
+ }
+
+ if (DisplayOutput) {
+ DisplayWrite( ARC_CONSOLE_OUTPUT, Buffer, Length, &Count);
+ }
+ }
+
+ va_end(arglist);
+ return 0;
+}
diff --git a/private/ntos/fw/alpha/fwrstb.c b/private/ntos/fw/alpha/fwrstb.c
new file mode 100644
index 000000000..d37a7636f
--- /dev/null
+++ b/private/ntos/fw/alpha/fwrstb.c
@@ -0,0 +1,172 @@
+#if defined(ALPHA)
+
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ fwrstb.c
+
+Abstract:
+
+
+ This module implements routines to initialize and verify the
+ restart block for JENSEN.
+
+Author:
+
+ Joe Notarangelo 24-Feb-1993
+
+Environment:
+
+ Firmware in Kernel mode only.
+
+Revision History:
+
+--*/
+
+
+#include "fwp.h"
+
+
+VOID
+FwInitializeRestartBlock(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function initializes the restart block for JENSEN. This must
+ be called after all other System Parameter Block initialization is
+ done, because it creates the Restart Block structures after the
+ EISA Adapter vector.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PRESTART_BLOCK RestartBlock;
+ PALPHA_RESTART_SAVE_AREA AlphaSaveArea;
+
+ //
+ // The following steps must be taken here:
+ //
+ // 1. Determine the restart block pointer
+ // 2. Write the restart block pointer into the system block
+ // 3. Initialize the restart block
+ // a. Set the length of the restart block
+ // b. Initialize the signature
+ // c. Clear the halt reason code in the Alpha area
+ // d. Clear the logout frame pointer in the Alpha area
+ //
+
+ //
+ // Create the restart block after EISA Adapter Vector. The base
+ // address must be at least quadword aligned. To be safe, align
+ // it to a cache block.
+ //
+
+ SYSTEM_BLOCK->RestartBlock = (PVOID)
+ (((ULONG)SYSTEM_BLOCK->Adapter0Vector +
+ SYSTEM_BLOCK->Adapter0Length +
+ KeGetDcacheFillSize())
+ &
+ ~(KeGetDcacheFillSize() - 1));
+
+ //
+ // Initialize the restart block.
+ //
+
+ RestartBlock = SYSTEM_BLOCK->RestartBlock;
+
+ //
+ // The -4 accounts for the fact that the Alpha AXP restart save
+ // area actually begins at the last longword of the Restart Block.
+ //
+
+ RestartBlock->Length = sizeof(RESTART_BLOCK) +
+ sizeof(ALPHA_RESTART_SAVE_AREA) -
+ 4;
+
+ RestartBlock->Signature = ARC_RESTART_BLOCK_SIGNATURE;
+
+ AlphaSaveArea = (PALPHA_RESTART_SAVE_AREA)&RestartBlock->u.SaveArea;
+
+ AlphaSaveArea->HaltReason = AXP_HALT_REASON_HALT;
+
+ AlphaSaveArea->LogoutFrame = NULL;
+
+}
+
+
+BOOLEAN
+FwVerifyRestartBlock(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function verifies that the restart block for JENSEN is valid.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ TRUE is returned if the restart block is valid, otherwise FALSE is
+ returned.
+
+--*/
+{
+
+ PRESTART_BLOCK RestartBlock = SYSTEM_BLOCK->RestartBlock;
+ LONG RestartBlockSum;
+ ULONG I;
+ ULONG RestartBlockLength;
+ PLONG CheckSumPointer;
+
+ //
+ // Is the restart block valid?
+ //
+
+ if (RestartBlock->Signature != ARC_RESTART_BLOCK_SIGNATURE ) {
+ return FALSE;
+ }
+
+ //
+ // Is the checksum valid?
+ //
+
+ RestartBlockSum = 0;
+ RestartBlockLength = RestartBlock->Length;
+ CheckSumPointer = (PLONG)RestartBlock;
+
+ for (I = 0; I < RestartBlockLength; I += 4 ) {
+ RestartBlockSum += *CheckSumPointer++;
+ }
+
+ if (RestartBlockSum != 0) {
+ return FALSE;
+ }
+
+ //
+ // All checks have passed.
+ //
+
+ return TRUE;
+
+}
+
+#endif //ALPHA
diff --git a/private/ntos/fw/alpha/fwsignal.c b/private/ntos/fw/alpha/fwsignal.c
new file mode 100644
index 000000000..9e0df889b
--- /dev/null
+++ b/private/ntos/fw/alpha/fwsignal.c
@@ -0,0 +1,381 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ fwsignal.c
+
+Abstract:
+
+ This module implements the ARC firmware Signal Handling Functions.
+
+Author:
+
+ Lluis Abello (lluis) 24-Sep-1991
+
+
+Revision History:
+
+ 22-May-1992 John DeRosa [DEC]
+
+ Modified this for Alpha. The vestigal interrupt and signal
+ support was removed, and keyboard input is done by polling.
+
+--*/
+
+#include "fwp.h"
+#include "iodevice.h"
+
+extern KEYBOARD_BUFFER KbdBuffer;
+
+//
+// Keyboard static variables.
+//
+
+BOOLEAN Scan0xE0 = FALSE;
+
+// 1111 1 1111122222222 2 2333333333344 4 44444445555 5 5 55
+// Character # 234567890123 4 5678901234567 8 9012345678901 2 34567890123 4 5 67
+PCHAR NormalLookup = "1234567890-=\b\tqwertyuiop[]\n\0asdfghjkl;'`\0\\zxcvbnm,./\0\0\0 ";
+PCHAR ShiftedLookup = "!@#$%^&*()_+\b\0QWERTYUIOP{}\n\0ASDFGHJKL:\"~\0\|ZXCVBNM<>?\0\0\0 ";
+
+extern BOOLEAN FwLeftShift;
+extern BOOLEAN FwRightShift;
+extern BOOLEAN FwControl;
+extern BOOLEAN FwAlt;
+extern BOOLEAN FwCapsLock;
+
+
+VOID
+StoreKeyboardChar(
+ IN UCHAR Character
+ )
+/*++
+
+Routine Description:
+
+ This routine stores the given character into the circular
+ buffer if there is enough room. Otherwise the character is lost.
+
+Arguments:
+
+ Character - Supplies the translated scan code to store into the buffer
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // Store scan code in buffer if there is room.
+ //
+ if (((KbdBuffer.WriteIndex+1) % KBD_BUFFER_SIZE) != KbdBuffer.ReadIndex) {
+ KbdBuffer.WriteIndex = (KbdBuffer.WriteIndex+1) % KBD_BUFFER_SIZE;
+ KbdBuffer.Buffer[KbdBuffer.WriteIndex] = Character;
+ }
+}
+
+
+VOID
+TranslateScanCode(
+ IN UCHAR Scan
+ )
+
+/*++
+
+Routine Description:
+
+ This routine translates the given keyboard scan code into an
+ ASCII character and puts it in the circular buffer.
+
+Arguments:
+
+ Scan - Supplies the scan code read from the keyboard.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR FwControlCharacter=0;
+ UCHAR FwFunctionCharacter;
+ BOOLEAN MakeCode;
+ UCHAR Char;
+
+ //
+ // Check 0xE0, which introduces a two key sequence.
+ //
+
+ if (Scan == 0xE0) {
+ Scan0xE0 = TRUE;
+ return;
+ }
+
+ if (Scan0xE0 == TRUE) {
+
+ //
+ // Check for PrintScrn (used as SysRq, also found in its true Alt
+ // form below).
+ //
+
+ if (Scan == KEY_PRINT_SCREEN) {
+ StoreKeyboardChar(ASCII_SYSRQ);
+ Scan0xE0 = FALSE;
+ return;
+ }
+ }
+
+ //
+ // Look for scan codes that indicate shift, control, or alt keys. Bit 7
+ // of scan code indicates upward or downward keypress.
+ //
+ // N.B. By masking the scan code with 0x7f, both the make and break codes
+ // are covered.
+ //
+
+ MakeCode = !(Scan & 0x80);
+ switch (Scan & 0x7F) {
+
+ case KEY_LEFT_SHIFT:
+ FwLeftShift = MakeCode;
+ return;
+
+ case KEY_RIGHT_SHIFT:
+ FwRightShift = MakeCode;
+ return;
+
+ case KEY_CONTROL:
+ FwControl = MakeCode;
+ Scan0xE0 = FALSE;
+ return;
+
+ case KEY_ALT:
+ FwAlt = MakeCode;
+ return;
+
+ default:
+ break;
+ }
+
+ //
+ // The rest of the keys only do something on make.
+ //
+
+ if (MakeCode) {
+
+ //
+ // Check for control keys.
+ //
+
+ switch (Scan) {
+
+ case KEY_UP_ARROW:
+ FwControlCharacter = 'A';
+ break;
+
+ case KEY_DOWN_ARROW:
+ FwControlCharacter = 'B';
+ break;
+
+ case KEY_RIGHT_ARROW:
+ FwControlCharacter = 'C';
+ break;
+
+ case KEY_LEFT_ARROW:
+ FwControlCharacter = 'D';
+ break;
+
+ case KEY_HOME:
+ FwControlCharacter = 'H';
+ break;
+
+ case KEY_END:
+ FwControlCharacter = 'K';
+ break;
+
+ case KEY_PAGE_UP:
+ FwControlCharacter = '?';
+ break;
+
+ case KEY_PAGE_DOWN:
+ FwControlCharacter = '/';
+ break;
+
+ case KEY_INSERT:
+ FwControlCharacter = '@';
+ break;
+
+ case KEY_DELETE:
+ FwControlCharacter = 'P';
+ break;
+
+ case KEY_SYS_REQUEST:
+ StoreKeyboardChar(ASCII_SYSRQ);
+ return;
+
+ case KEY_ESC:
+ StoreKeyboardChar(ASCII_ESC);
+ return;
+
+ case KEY_CAPS_LOCK:
+ FwCapsLock = !FwCapsLock;
+ return;
+
+ case KEY_F1:
+ FwControlCharacter = 'O';
+ FwFunctionCharacter = 'P';
+ break;
+
+ case KEY_F2:
+ FwControlCharacter = 'O';
+ FwFunctionCharacter = 'Q';
+ break;
+
+ case KEY_F3:
+ FwControlCharacter = 'O';
+ FwFunctionCharacter = 'w';
+ break;
+
+ case KEY_F4:
+ FwControlCharacter = 'O';
+ FwFunctionCharacter = 'x';
+ break;
+
+ case KEY_F5:
+ FwControlCharacter = 'O';
+ FwFunctionCharacter = 't';
+ break;
+
+ case KEY_F6:
+ FwControlCharacter = 'O';
+ FwFunctionCharacter = 'u';
+ break;
+
+ case KEY_F7:
+ FwControlCharacter = 'O';
+ FwFunctionCharacter = 'q';
+ break;
+
+ case KEY_F8:
+ FwControlCharacter = 'O';
+ FwFunctionCharacter = 'r';
+ break;
+
+ case KEY_F9:
+ FwControlCharacter = 'O';
+ FwFunctionCharacter = 'p';
+ break;
+
+ case KEY_F10:
+ FwControlCharacter = 'O';
+ FwFunctionCharacter = 'M';
+ break;
+
+// case KEY_F11:
+// FwControlCharacter = 'O';
+// FwFunctionCharacter = 'A';
+// break;
+//
+// case KEY_F12:
+// FwControlCharacter = 'O';
+// FwFunctionCharacter = 'B';
+// break;
+
+ default:
+
+ //
+ // Some kind of character.
+ //
+
+ Char = 0;
+
+ //
+ // Check for keypad + or -. This is done here because we only
+ // recognize a two keypad keys. Full keypad support should be
+ // done by a lookup table.
+ //
+
+ if (Scan == KEY_KEYPAD_MINUS) {
+
+ Char = '-';
+
+ } else if (Scan == KEY_KEYPAD_PLUS) {
+
+ Char = '+';
+
+ } else if (((Scan >= 16) && (Scan <= 25)) ||
+ ((Scan >= 30) && (Scan <= 38)) ||
+ ((Scan >= 44) && (Scan <= 50))) {
+
+ //
+ // Alphabetic character
+ //
+
+ if (FwControl) {
+
+ //
+ // Control character.
+ //
+ // This works for ^A -- ^Z.
+ //
+
+ Char = NormalLookup[Scan - 2] - 'A';
+
+ } else {
+
+ //
+ // ASCII alphanumeric character. Set up to store
+ // either the main key or shifted key character.
+ //
+
+ if (((FwLeftShift || FwRightShift) && !FwCapsLock) ||
+ (!(FwLeftShift || FwRightShift) && FwCapsLock)) {
+ Char = ShiftedLookup[Scan - 2];
+ } else {
+ Char = NormalLookup[Scan - 2];
+ }
+ }
+
+ } else if ((Scan > 1) && (Scan < 58)) {
+
+ //
+ // It is ASCII but not alpha, so do not shift on CapsLock.
+ //
+
+ if (FwLeftShift || FwRightShift) {
+ Char = ShiftedLookup[Scan - 2];
+ } else {
+ Char = NormalLookup[Scan - 2];
+ }
+ }
+
+ //
+ // If a character, store it in buffer.
+ //
+
+ if (Char) {
+ StoreKeyboardChar(Char);
+ return;
+ }
+ break;
+ }
+
+ //
+ // This is for ASCII_CSI sequences, not normal control characters.
+ //
+
+ if (FwControlCharacter) {
+ StoreKeyboardChar(ASCII_CSI);
+ StoreKeyboardChar(FwControlCharacter);
+ if (FwControlCharacter == 'O') {
+ StoreKeyboardChar(FwFunctionCharacter);
+ }
+ return;
+ }
+ }
+}
diff --git a/private/ntos/fw/alpha/fwstring.h b/private/ntos/fw/alpha/fwstring.h
new file mode 100644
index 000000000..ae0522c63
--- /dev/null
+++ b/private/ntos/fw/alpha/fwstring.h
@@ -0,0 +1,301 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ fwstring.h
+
+Abstract:
+
+ This module contains the extern statements and #defines for
+ the firmware English strings. This is fwstring.h and the
+ jzstring.h files concatenated together.
+
+Author:
+
+ David M. Robinson (davidro) 21-May-1993
+
+
+Revision History:
+
+ 7-June-1993 John DeRosa [DEC]
+
+ Modified for Alpha AXP and Jensen.
+
+--*/
+
+//
+// Common strings.
+//
+
+extern PCHAR FW_OK_MSG;
+extern PCHAR FW_CRLF_MSG;
+extern PCHAR FW_ERROR2_MSG;
+
+//
+// Firmware strings.
+//
+
+extern PCHAR FW_BOOT_MSG;
+#define FW_BOOT_MSG_SIZE 5
+
+extern PCHAR FW_INVALID_RESTART_BLOCK_MSG;
+extern PCHAR FW_NOT_ENOUGH_ENTRIES_MSG;
+extern PCHAR FW_FILESYSTEM_NOT_REQ_MSG;
+extern PCHAR FW_UNKNOWN_SECTION_TYPE_MSG;
+extern PCHAR FW_UNKNOWN_RELOC_TYPE_MSG;
+extern PCHAR FW_UNKNOWN_ROM_MSG;
+extern PCHAR FW_DEFAULT_MSG;
+extern PCHAR FW_FIRMWARE_UPDATE_SEARCH_MSG;
+extern PCHAR FW_NO_BOOT_SELECTIONS_MSG;
+extern PCHAR FW_DO_NOT_POWER_OFF_MSG;
+extern PCHAR FW_USE_ARROW_AND_ENTER_MSG;
+extern PCHAR FW_AUTOBOOT_MSG;
+extern PCHAR FW_INTERNAL_ERROR_ENVIRONMENT_VARS_MSG;
+extern PCHAR FW_PROGRAM_TO_RUN_MSG;
+extern PCHAR FW_PATHNAME_NOT_DEF_MSG;
+extern PCHAR FW_PRESS_ANY_KEY_MSG;
+extern PCHAR FW_ERROR_CODE_MSG;
+extern PCHAR FW_PRESS_ANY_KEY2_MSG;
+extern PCHAR FW_INITIALIZING_MSG;
+extern PCHAR FW_CONSOLE_IN_ERROR_MSG;
+extern PCHAR FW_CONSOLE_TRYING_TO_OPEN_MSG;
+extern PCHAR FW_CONSOLE_IN_FAILSAFE_ERROR_MSG;
+extern PCHAR FW_CONSOLE_OUT_FAILSAFE_ERROR_MSG;
+extern PCHAR FW_CONSOLE_IN_PLEASE_REPAIR_MSG;
+extern PCHAR FW_CONSOLE_OUT_PLEASE_REPAIR_MSG;
+extern PCHAR FW_CONSOLE_IN_ERROR2_MSG;
+extern PCHAR FW_CONSOLE_OUT_ERROR_MSG;
+extern PCHAR FW_CONSOLE_OUT_ERROR2_MSG;
+extern PCHAR FW_CONTACT_FIELD_SERVICE_MSG;
+extern PCHAR FW_SPIN_DISKS_MSG;
+extern PCHAR FW_NO_CDROM_DRIVE_MSG;
+extern PCHAR FW_WNT_INSTALLATION_ABORTED_MSG;
+
+extern PCHAR FW_MARKING_EISA_BUFFER_MSG;
+extern PCHAR FW_MARKING_EISA_BUFFER_ERROR_MSG;
+
+extern PCHAR FW_RED_BANNER_PRESSKEY_MSG;
+
+extern PCHAR FW_SYSTEM_INCONSISTENCY_WARNING_MSG[];
+#define FW_SYSTEM_INCONSISTENCY_WARNING_MSG_SIZE 3
+
+extern PCHAR FW_SYSTEM_INCONSISTENCY_WARNING_HOWTOFIX_MSG[];
+#define FW_SYSTEM_INCONSISTENCY_WARNING_HOWTOFIX_MSG_SIZE 3
+
+extern PCHAR FW_ERROR_MSG[];
+
+
+//
+// Halt, machine check messages
+//
+
+extern PCHAR FW_SYSRQ_MONITOR_MSG;
+extern PCHAR FW_FATAL_DMC_MSG;
+extern PCHAR FW_FATAL_MCINPALMODE_MSG;
+extern PCHAR FW_FATAL_UNKNOWN_MSG;
+extern PCHAR FW_FATAL_TAGCNTRL_PE_MSG;
+extern PCHAR FW_FATAL_TAG_PE_MSG;
+extern PCHAR FW_FATAL_HEACK_MSG;
+extern PCHAR FW_FATAL_SEACK_MSG;
+extern PCHAR FW_FATAL_ECC_ERROR_MSG;
+extern PCHAR FW_FATAL_QWLWLW_MSG;
+extern PCHAR FW_FATAL_PE_MSG;
+extern PCHAR FW_FATAL_MULTIPLE_EXT_TAG_ERRORS_MSG;
+extern PCHAR FW_FATAL_MULTIPLE_FILL_ERRORS_MSG;
+
+
+//
+// Menu types
+//
+
+extern PCHAR FW_MENU_BOOT_MSG;
+extern PCHAR FW_MENU_SUPPLEMENTARY_MSG;
+extern PCHAR FW_MENU_SETUP_MSG;
+extern PCHAR FW_MENU_BOOT_SELECTIONS_MSG;
+
+
+//
+// Menu strings
+//
+
+extern PCHAR BootMenuChoices[];
+extern PCHAR SupplementaryMenuChoices[];
+extern PCHAR OperatingSystemSwitchChoices[];
+extern PCHAR MachineProblemAreas[];
+
+#define NUMBER_OF_BOOT_CHOICES 4
+#define NUMBER_OF_SUPP_CHOICES 6
+#define NUMBER_OF_OS_CHOICES 4
+#define NUMBER_OF_MACHINE_PROBLEM_AREAS 8
+
+
+//
+// Monitor Strings.
+//
+
+extern PCHAR MON_INVALID_ARGUMENT_COUNT_MSG;
+extern PCHAR MON_UNALIGNED_ADDRESS_MSG;
+extern PCHAR MON_INVALID_VALUE_MSG;
+extern PCHAR MON_INVALID_REGISTER_MSG;
+extern PCHAR MON_BAD_IO_OPERATION_MSG;
+extern PCHAR MON_NOT_VALID_ADDRESS_MSG;
+extern PCHAR MON_INVALID_ADDRESS_RANGE_MSG;
+extern PCHAR MON_AVAILABLE_HW_DEVICES_MSG;
+extern PCHAR MON_MONITOR_MSG;
+extern PCHAR MON_PRESS_H_MSG;
+extern PCHAR MON_EXCEPTION_MSG;
+extern PCHAR MON_NO_RETURN_MSG;
+extern PCHAR MON_RESET_MACHINE_MSG;
+extern PCHAR MON_UNRECOGNIZED_COMMAND_MSG;
+
+extern PCHAR MON_HELP_TABLE[];
+#define MON_HELP_SIZE 16
+
+//
+// Selftest module strings.
+//
+
+extern PCHAR ST_ALL_IO_TO_SERIAL_LINES_MSG;
+extern PCHAR ST_BAD_PAGE_SIZE_MSG;
+extern PCHAR ST_BAD_MEMORY_SIZE_MSG;
+extern PCHAR ST_BAD_CLOCK_PERIOD_MSG;
+extern PCHAR ST_EISA_ISP_ERROR_MSG;
+extern PCHAR FW_ARC_MULTIBOOT_MSG;
+extern PCHAR FW_COPYRIGHT_MSG;
+
+//
+// FailSafe Booter strings. If necessary, this could be an entirely
+// separate message file to conserve space.
+//
+
+extern PCHAR FSB_MSG;
+extern PCHAR FSB_WHY_RUNNING_MSG;
+extern PCHAR FSB_FIELD_SERVICE_MSG;
+extern PCHAR FSB_LOOKING_FOR_MSG;
+extern PCHAR FSB_UPGRADE_ABORTED_MSG;
+extern PCHAR FSB_POWER_CYCLE_TO_REBOOT_MSG;
+
+
+//
+// Stubs strings.
+//
+
+extern PCHAR ST_RESERVED_ROUTINE_MSG;
+extern PCHAR ST_STACK_UNDERFLOW_1_MSG;
+extern PCHAR ST_STACK_UNDERFLOW_2_MSG;
+extern PCHAR ST_STACK_UNDERFLOW_3_MSG;
+extern PCHAR ST_HIT_KEY_FOR_MONITOR_MSG;
+extern PCHAR ST_BUGCHECK_MSG;
+extern PCHAR ST_ASSERT_MSG;
+extern PCHAR ST_HIT_KEY_FOR_REBOOT_MSG;
+
+
+//
+// Definitions for the built-in ROM setup utility
+//
+
+#define SS_CRLF_MSG FW_CRLF_MSG
+
+//
+// Prompt strings.
+//
+
+extern PCHAR SS_TOO_MANY_BOOT_SELECTIONS;
+extern PCHAR SS_COUNTDOWN_MSG;
+extern PCHAR SS_OSLOADER_MSG;
+extern PCHAR SS_OS_MSG;
+extern PCHAR SS_OS_ROOT_MSG;
+extern PCHAR SS_BOOT_NAME_MSG;
+extern PCHAR SS_INIT_DEBUG_MSG;
+extern PCHAR SS_CANT_SET_VARIABLE_MSG;
+extern PCHAR SS_NO_SELECTIONS_TO_DELETE_MSG;
+extern PCHAR SS_SELECTION_TO_DELETE_MSG;
+extern PCHAR SS_ENVIR_FOR_BOOT_MSG;
+extern PCHAR SS_FORMAT1_MSG;
+extern PCHAR SS_USE_ARROWS_MSG;
+extern PCHAR SS_NO_SELECTIONS_TO_EDIT_MSG;
+extern PCHAR SS_SELECTION_TO_EDIT_MSG;
+extern PCHAR SS_NO_SELECTIONS_TO_REARRANGE_MSG;
+extern PCHAR SS_PICK_SELECTION_MSG;
+extern PCHAR SS_SHOULD_AUTOBOOT_MSG;
+extern PCHAR SS_ENVIRONMENT_VARS_MSG;
+extern PCHAR SS_CHECKING_MSG;
+extern PCHAR SS_CHECKING_BOOT_SEL_NUMBER_MSG;
+extern PCHAR SS_FORMAT2_MSG;
+extern PCHAR SS_VARIABLE_NULL_MSG;
+extern PCHAR SS_CANT_BE_FOUND_MSG;
+extern PCHAR SS_PROBLEMS_FOUND_MSG;
+extern PCHAR SS_PROBLEMS_CHOOSE_AN_ACTION_MSG;
+extern PCHAR SS_SELECTION_MENU_MSG;
+extern PCHAR SS_ECU_WILL_NOW_REBOOT_MSG;
+extern PCHAR SS_RESET_TO_FACTORY_DEFAULTS_WARNING_MSG;
+extern PCHAR SS_ARE_YOU_SURE_MSG;
+extern PCHAR SS_ESCAPE_FROM_SETUP_MSG;
+extern PCHAR SS_PRESS_KEY_MSG;
+extern PCHAR SS_PRESS_KEY2_MSG;
+extern PCHAR SS_NAME_MSG;
+extern PCHAR SS_VALUE_MSG;
+extern PCHAR SS_NO_NVRAM_SPACE_MSG;
+extern PCHAR SS_NVRAM_CHKSUM_MSG;
+extern PCHAR SS_ROM_UPDATE_IN_PROGRESS_MSG;
+extern PCHAR SS_ROM_UPDATE_FAILED_MSG;
+extern PCHAR SS_SELECT_MEDIA_MSG;
+extern PCHAR SS_SELECT_MONITOR_RESOLUTION_MSG;
+extern PCHAR SS_ENTER_FAT_OR_NTFS_PART_MSG;
+extern PCHAR SS_ENTER_PART_MSG;
+extern PCHAR SS_SELECT_SYS_PART_MSG;
+extern PCHAR SS_SCSI_HD_MSG;
+extern PCHAR SS_FL_MSG;
+extern PCHAR SS_SCSI_CD_MSG;
+extern PCHAR SS_NEW_SYS_PART_MSG;
+extern PCHAR SS_LOCATE_SYS_PART_MSG;
+extern PCHAR SS_ENTER_SCSI_ID_MSG;
+extern PCHAR SS_ENTER_FLOPPY_DRIVE_NUMBER_MSG;
+extern PCHAR SS_LOCATE_OS_PART_MSG;
+extern PCHAR SS_FLOPPY_SIZE_MSG;
+extern PCHAR SS_2ND_FLOPPY_MSG;
+extern PCHAR SS_SCSI_HOST_MSG;
+extern PCHAR SS_DEFAULT_SYS_PART_MSG;
+extern PCHAR SS_ENTER_DATE_MSG;
+extern PCHAR SS_ENTER_TIME_MSG;
+extern PCHAR SS_ILLEGAL_TIME_MSG;
+extern PCHAR SS_PM;
+extern PCHAR SS_AM;
+extern PCHAR SS_WHICH_OS_QUERY_MSG;
+extern PCHAR SS_BOOT_SELECTION_IS_MSG;
+extern PCHAR SS_POWER_CYCLE_FOR_NEW_OS_MSG;
+
+extern PCHAR SETUP_HELP_TABLE[];
+#define SETUP_HELP_TABLE_SIZE 18
+
+//
+// Menus.
+//
+
+extern PCHAR ProblemChoices[];
+#define NUMBER_OF_PROBLEMS 3
+
+extern PCHAR YesNoChoices[];
+#define NUMBER_OF_YES_NO 2
+
+extern PCHAR MediaChoices[];
+#define NUMBER_OF_MEDIA 3
+
+extern PCHAR ManageBootSelectionChoices[];
+#define NUMBER_OF_SS_MANAGE_BOOT_CHOICES 7
+
+extern PCHAR ResolutionChoices[];
+#define NUMBER_OF_RESOLUTIONS 4
+
+extern PCHAR FloppyChoices[];
+#define NUMBER_OF_FLOPPIES 3
+
+extern PCHAR Weekday[];
+
+extern PCHAR SetupMenuChoices[];
+#define NUMBER_OF_SETUP_MENU_CHOICES 14
+
+extern PCHAR OperatingSystemNames[];
diff --git a/private/ntos/fw/alpha/fwtime.c b/private/ntos/fw/alpha/fwtime.c
new file mode 100644
index 000000000..95ed0a83a
--- /dev/null
+++ b/private/ntos/fw/alpha/fwtime.c
@@ -0,0 +1,171 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ fwtime.c
+
+Abstract:
+
+ This module implements the ARC firmware time operations.
+
+Author:
+
+ David M. Robinson (davidro) 19-Aug-1991
+
+
+Revision History:
+
+ 21-July-1992 John DeRosa [DEC]
+
+ Made Alpha/Jensen modifications.
+
+--*/
+
+#include "fwp.h"
+#include "jxhalp.h"
+
+//
+// Static data.
+//
+
+TIME_FIELDS FwTime;
+ULONG Seconds;
+ULONG FwDays;
+
+
+ARC_STATUS
+FwTimeInitialize (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the time routine addresses.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ ESUCCESS is returned.
+
+--*/
+{
+
+ //
+ // Initialize the time routine addresses in the system
+ // parameter block.
+ //
+
+ (PARC_GET_TIME_ROUTINE)SYSTEM_BLOCK->FirmwareVector[GetTimeRoutine] =
+ FwGetTime;
+ (PARC_GET_RELATIVE_TIME_ROUTINE)SYSTEM_BLOCK->FirmwareVector[GetRelativeTimeRoutine] =
+ FwGetRelativeTime;
+
+ //
+ // Initialize pointers that the HAL routines use to access the RTC. Note
+ // that these routines are linked with the firmware and so this does not
+ // affect the actual HAL.
+ //
+
+ HalpEisaControlBase = (PVOID)EISA_IO_VIRTUAL_BASE;
+#ifndef ALPHA
+ // This does not exist on Alpha/Jensen.
+ HalpRealTimeClockBase = (PVOID)RTC_VIRTUAL_BASE;
+#endif
+
+ //
+ // Initialize static data.
+ //
+
+ Seconds = 0;
+ FwDays = 0;
+
+ return ESUCCESS;
+}
+
+PTIME_FIELDS
+FwGetTime (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine returns a time structure filled in with the current
+ time read from the RTC.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns a pointer to a time structure. If the time information is
+ valid, valid data is returned, otherwise all fields are returned as zero.
+
+--*/
+
+{
+ if (!HalQueryRealTimeClock(&FwTime)) {
+ FwTime.Year = 0;
+ FwTime.Month = 0;
+ FwTime.Day = 0;
+ FwTime.Hour = 0;
+ FwTime.Minute = 0;
+ FwTime.Second = 0;
+ FwTime.Milliseconds = 0;
+ FwTime.Weekday = 0;
+ }
+ return &FwTime;
+}
+
+
+ULONG
+FwGetRelativeTime (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine returns a ULONG which increases at a rate of one per second.
+ This routine must be called at least once per day for the number to maintain
+ an accurate count.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns a ULONG. If the time information is valid, valid
+ data is returned, otherwise a zero is returned.
+
+--*/
+
+{
+ TIME_FIELDS Time;
+ ULONG TempTime;
+
+ TempTime = Seconds;
+ if (HalQueryRealTimeClock(&Time)) {
+ Seconds = ((FwDays * 24 + Time.Hour) * 60 + Time.Minute) * 60 + Time.Second;
+ if (Seconds < TempTime) {
+ FwDays++;
+ Seconds += 24 * 60 * 60;
+ }
+ } else {
+ Seconds = 0;
+ }
+ return Seconds;
+}
+
diff --git a/private/ntos/fw/alpha/fwupusa.c b/private/ntos/fw/alpha/fwupusa.c
new file mode 100644
index 000000000..edc0d3d62
--- /dev/null
+++ b/private/ntos/fw/alpha/fwupusa.c
@@ -0,0 +1,168 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ fwupusa.c
+
+Abstract:
+
+ This module contains English strings for the firmware update
+ tool (jnupdate.exe).
+
+Author:
+
+ John DeRosa [DEC] 18-June-1993
+
+
+Revision History:
+
+--*/
+
+#include "ntos.h"
+
+
+//
+// Menus
+//
+
+#if defined(JENSEN)
+
+PCHAR UpdateLocationChoices[] = {
+ "Floppy #0\\jensfw.bin",
+ "CD-ROM\\jensfw.bin",
+ "Other location",
+ "Exit"
+ };
+
+#elif defined(MORGAN)
+
+PCHAR UpdateLocationChoices[] = {
+ "Floppy #0\\mrgnfw.bin",
+ "CD-ROM\\mrgnfw.bin",
+ "Other location",
+ "Exit"
+ };
+
+#endif
+
+
+//
+// Machine-specific strings
+//
+
+#ifdef JENSEN
+
+PCHAR FWUP_INTRO1_MSG = " DECpc AXP 150 FlashFile Update Utility, revision %s\r\n";
+PCHAR FWUP_DEFAULT_FLOPPY_LOCATION = "eisa()disk()fdisk()jensfw.bin";
+PCHAR FWUP_DEFAULT_CDROM_FILENAME = "\\jensfw.bin";
+
+#elif defined(MORGAN)
+
+PCHAR FWUP_INTRO1_MSG = " Morgan FlashFile Update Utility, revision %s\r\n";
+PCHAR FWUP_DEFAULT_FLOPPY_LOCATION = "eisa()disk()fdisk()mrgnfw.bin";
+PCHAR FWUP_DEFAULT_CDROM_FILENAME = "\\mrgnfw.bin";
+
+PCHAR FWUP_ABOUT_TO_WRITE_ROM_MSG = "about to write FLASH ROM #%d\r\n";
+PCHAR FWUP_ROM_CHIP_SELECT_MSG = "MorganFlashRomChipSelect = %d, must be 1 or 2\r\n";
+PCHAR FWUP_ROM_UPDATE_SUCCEEDED_MSG = "FLASH ROM update succeeded.\r\n";
+PCHAR FWUP_ROM_UPDATE_FAILED_MSG = "FLASH ROM update failed.\r\n";
+
+#endif
+
+
+//
+// Common strings
+//
+
+PCHAR FWUP_INTRO2_MSG = " Copyright (c) 1992, 1993 Microsoft Corporation\r\n Copyright (c) 1993 Digital Equipment Corporation\r\n\n\n";
+PCHAR FWUP_INTRO3_MSG = " This will update your machine's firmware.\r\n\n";
+PCHAR FWUP_SELECT_LOCATION_MSG = " Select location of update file.\r\n\n";
+PCHAR FWUP_USE_ARROW_KEYS_MSG = " Use the arrow keys to select, then press Enter.\r\n";
+PCHAR FWUP_HIT_ESC_TO_ABORT_MSG = " Hit Escape to abort.\r\n";
+PCHAR FWUP_LOCATION_OF_UPDATE_FILE_MSG = " Location of update file: ";
+PCHAR FWUP_UNDEFINED_PATHNAME_MSG = " Pathname is not defined.\r\n";
+PCHAR FWUP_BAD_PATHNAME_MSG = " Bad Pathname: %s\r\n";
+PCHAR FWUP_LOCATING_THE_FILE_MSG = " Locating the update file...\r\n";
+PCHAR FWUP_UPDATE_FILE_IS_GOOD_MSG = " The update file is good!\r\n The name of this firmware update is...:\r\n\n";
+PCHAR FWUP_ARE_YOU_REALLY_SURE_MSG = "\r\n Are you *really* sure?\r\n";
+PCHAR FWUP_FAILED_UPDATE_MSG = "Your machine state may have been corrupted. Re-do the\r\ninstallation immediately, or call Digital Field Service.\r\n";
+PCHAR FWUP_SUCCESSFUL_UPDATE_MSG = "\r\n\nThe update has succeeded. Power-cycle the machine to see the changes.\r\n\n";
+
+PCHAR FWUP_YORN_MSG = "\r\nY = continue, N = iterate: ";
+UCHAR FWUP_LOWER_Y = 'y';
+UCHAR FWUP_UPPER_Y = 'Y';
+
+PCHAR FWUP_UNKNOWN_ROM_MSG = "?? Unknown ROM in machine.\r\n";
+PCHAR FWUP_ROM_TYPE_IS_MSG = "Machine ROM type is 0x%x.\r\n";
+
+PCHAR FWUP_CLEARING_LOW_PROM_BLOCK_MSG = "Clearing the low PROM block...\r\n";
+PCHAR FWUP_BLOCK_CANNOT_BE_ERASED_MSG = "** Block %d cannot be erased after %d tries.\r\n";
+PCHAR FWUP_KEEP_TRYING_MSG = "\r\nShould I keep trying?\r\n";
+PCHAR FWUP_CLEARING_AND_WRITING_HIGHER_BLOCKS_MSG = "Clearing and writing the higher PROM blocks";
+PCHAR FWUP_SOME_BLOCKS_CANNOT_BE_ERASED_MSG = "\r\n** Some blocks cannot be erased or written after %d attempts.\r\n";
+PCHAR FWUP_LOW_BLOCK_CANNOT_BE_ERASED_MSG = "\r\n** The low block cannot be erased or written after %d attempts.\r\n";
+PCHAR FWUP_ERASE_FAILURES_MSG = "Erase failures: ";
+PCHAR FWUP_WRITE_FAILURES_MSG = "\r\nWrite failures: ";
+PCHAR FWUP_NONE_MSG = "None.";
+PCHAR FWUP_INTERNAL_ERROR_MSG = "** INTERNAL JNUPDATE ERROR **";
+PCHAR FWUP_DO_YOU_WISH_TO_KEEP_TRYING_MSG = "\r\nDo you wish to keep trying?\r\n";
+PCHAR FWUP_WRITING_THE_BLOCK_MSG = "Writing the PROM block.";
+PCHAR FWUP_WRITING_THE_LOW_BLOCK_MSG = "\r\nWriting the low PROM block.";
+PCHAR FWUP_BLOCK_CANNOT_BE_ERASED_AFTER_10_MSG = "\r\n? The block could not be erased after 10 tries!\r\n";
+PCHAR FWUP_ERASURE_VERIFICATION_FAILED_MSG = "\r\n? The block failed erasure verification!\r\n";
+PCHAR FWUP_BAD_DATA_MSG = "\r\n?? BAD DATA: ROM: %x = %x ";
+PCHAR FWUP_BUFFER_MSG = "BUFFER: %x = %x";
+
+PCHAR FWUP_READ_CANT_OPEN_MSG = "Error: Cannot open the update file.\r\n Check the filespec and make sure the update device is present.\r\n";
+PCHAR FWUP_READ_CANT_GET_FILE_INFO_MSG = "Error: Cannot get file information from file system.\r\n The file system may be corrupted.\r\n";
+PCHAR FWUP_READ_BAD_SIZE_MSG = "Error: The update file is too small or too large to be legitimate.\r\n Contact your Digital Sales or Field Service representative.\r\n";
+PCHAR FWUP_READ_NOT_ENOUGH_MEMORY = "Error: %d. pages of memory could not be found to read in the update file.\r\n";
+PCHAR FWUP_READ_READING_MSG = " Reading the update file...\r\n";
+PCHAR FWUP_READ_BAD_READ_COUNT_MSG = "Error: Wanted to read %d. bytes and instead read %d. bytes\r\n";
+PCHAR FWUP_READ_VERIFYING_CHECKSUM_MSG = " Verifying the checksum...\r\n";
+PCHAR FWUP_READ_BAD_CHECKSUM_MSG = "Error: Additive checksum was 0x%x; it should be 0.\r\n";
+PCHAR FWUP_READ_IDENTIFIER_TOO_LONG_MSG = "Error: Identifier string is too long.\r\n";
+PCHAR FWUP_READ_BAD_START_BLOCK_MSG = "Error: Starting ROM block number is %d.\r\n";
+PCHAR FWUP_READ_BAD_BINARY_DATA_MSG = "Error: Binary data is not a multiple of 64KB.\r\n";
+PCHAR FWUP_READ_TOO_MUCH_DATA_MSG = "Error: Too much binary data (%d. %d.).\r\n";
+
+PCHAR FWUP_PRESS_Y_TO_CONTINUE_MSG = " Press the \"Y\" key to continue with the update.\r\n Hit any other key to abort.\r\n";
+PCHAR FWUP_UPDATE_ABORTED_MSG = "\r\n *** The update has been aborted!\r\n";
+
+PCHAR FWUP_ERROR_MSG[] = {
+ "Argument list is too long",
+ "Access violation",
+ "Resource temporarily unavailable",
+ "Bad image file type",
+ "Device is busy",
+ "Fault occured",
+ "Invalid argument",
+ "Device error",
+ "File is a directory",
+ "Too many open files",
+ "Too many links",
+ "Name is too long",
+ "Bad device name/number or partition number",
+ "No such file or directory",
+ "Execute format error",
+ "Not enough memory",
+ "No space left on device",
+ "File is not a directory",
+ "Inappropriate directory path or control operation",
+ "Media not loaded",
+ "Read-only file system"
+};
+
+PCHAR FWUP_ERROR_CODE_MSG = "Error code = %d";
+
+//
+// Strings defined in fwusa.c that must also be defined here
+// because of code that is common between jnupdate and the firmware.
+//
+
+PCHAR SS_PRESS_KEY_MSG = " Press any key to continue...\r\n";
+PCHAR ST_STACK_UNDERFLOW_1_MSG = "\r\n\n************\r\n************\r\n? Internal Firmware Error!!\r\n Reason: STACK UNDERFLOW\r\n\n";
+PCHAR ST_STACK_UNDERFLOW_2_MSG = "Caller = %x, Caller of the Caller = %x\r\n";
+PCHAR ST_STACK_UNDERFLOW_3_MSG = "Requested area = %x, Stack bottom = %x\r\n\n";
diff --git a/private/ntos/fw/alpha/fwusa.c b/private/ntos/fw/alpha/fwusa.c
new file mode 100644
index 000000000..c4e84b122
--- /dev/null
+++ b/private/ntos/fw/alpha/fwusa.c
@@ -0,0 +1,470 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ fwusa.c
+
+Abstract:
+
+ This module contains the fw english strings.
+
+Author:
+
+ David M. Robinson (davidro) 21-May-1993
+
+
+Revision History:
+
+ 7-June-1993 John DeRosa [DEC]
+
+ Modified for Alpha AXP and Jensen. This is now the fwusa.c module
+ and the jzusa.c module.
+
+--*/
+
+#include "ntos.h"
+
+//
+// Common strings.
+//
+
+PCHAR FW_OK_MSG = " ..OK.";
+PCHAR FW_CRLF_MSG = "\r\n";
+PCHAR FW_ERROR2_MSG = "\r\n Error: ";
+
+//
+// Firmware strings.
+//
+
+PCHAR FW_INVALID_RESTART_BLOCK_MSG = "Invalid Restart Block\r\n";
+PCHAR FW_NOT_ENOUGH_ENTRIES_MSG = "Error: Not enough entries in the lookup table.\n";
+PCHAR FW_FILESYSTEM_NOT_REQ_MSG = "File system not recognized.\r\n";
+PCHAR FW_UNKNOWN_SECTION_TYPE_MSG = "Unknown section type\r\n";
+PCHAR FW_UNKNOWN_RELOC_TYPE_MSG = "Relocator: Unknown relocation type\r\n";
+PCHAR FW_UNKNOWN_ROM_MSG = "?? Unknown ROM in machine. Call Digital Field Service.\r\n";
+PCHAR FW_BOOT_MSG = "Boot ";
+PCHAR FW_DEFAULT_MSG = " (Default)";
+PCHAR FW_FIRMWARE_UPDATE_SEARCH_MSG = "Searching floppy and CD-ROM for the firmware update tool...\r\n";
+PCHAR FW_NO_BOOT_SELECTIONS_MSG = "No boot selections, press any key to continue";
+PCHAR FW_DO_NOT_POWER_OFF_MSG = "\r\n Do not power off the machine...";
+PCHAR FW_USE_ARROW_AND_ENTER_MSG = " Use the arrow keys to select, then press Enter.\r\n";
+PCHAR FW_AUTOBOOT_MSG = " Seconds until auto-boot, select another option to override:\r\n";
+PCHAR FW_INTERNAL_ERROR_ENVIRONMENT_VARS_MSG = "Internal error, too many environment variables!\r\n";
+PCHAR FW_PROGRAM_TO_RUN_MSG = " Program to run: ";
+PCHAR FW_PATHNAME_NOT_DEF_MSG = " Pathname is not defined\r\n";
+PCHAR FW_PRESS_ANY_KEY_MSG = "\n\r Press any key to continue...\n\r";
+PCHAR FW_ERROR_CODE_MSG = "Error code = %d";
+PCHAR FW_PRESS_ANY_KEY2_MSG = ", press any key to continue";
+PCHAR FW_INITIALIZING_MSG = "\r\n Initializing firmware...";
+PCHAR FW_CONSOLE_IN_ERROR_MSG = "\r\n Error: Firmware could not open StandardIn\r\n";
+PCHAR FW_CONSOLE_TRYING_TO_OPEN_MSG = " Trying to open %s instead...";
+PCHAR FW_CONSOLE_IN_FAILSAFE_ERROR_MSG = "\r\n Firmware could not open failsafe StandardIn!\r\n";
+PCHAR FW_CONSOLE_OUT_FAILSAFE_ERROR_MSG = "\r\n Firmware could not open failsafe StandardOut!\r\n";
+PCHAR FW_CONSOLE_IN_PLEASE_REPAIR_MSG = " Please repair the CONSOLEIN environment variable before you boot\r\n the operating system.\r\n";
+PCHAR FW_CONSOLE_OUT_PLEASE_REPAIR_MSG = " Please repair the CONSOLEOUT environment variable before you boot\r\n the operating system.\r\n";
+PCHAR FW_CONSOLE_IN_ERROR2_MSG = "\r\n Error: Fid for StandardIn device is not zero\r\n";
+PCHAR FW_CONSOLE_OUT_ERROR_MSG = "\r\n Error: Firmware could not open StandardOut\r\n";
+PCHAR FW_CONSOLE_OUT_ERROR2_MSG = "\r\n Error: Fid for StandardOut device is not one\r\n";
+PCHAR FW_CONTACT_FIELD_SERVICE_MSG = " Contact Digital Field Service.\r\n";
+PCHAR FW_SPIN_DISKS_MSG = " Spinning up disks";
+PCHAR FW_NO_CDROM_DRIVE_MSG = "\r\n\n CD-ROM drive not found.";
+PCHAR FW_WNT_INSTALLATION_ABORTED_MSG = "\r\n\n Windows NT installation has been aborted.\r\n";
+
+#ifdef EISA_PLATFORM
+PCHAR FW_MARKING_EISA_BUFFER_MSG = "\r\nMarking EISA buffer: addr 0x%x, size 0x%x...\r\n";
+PCHAR FW_MARKING_EISA_BUFFER_ERROR_MSG = "? ERROR during memory descriptor init: cannot allocate EISA buffer.\r\n Error information: %x, %x, %x, %x.\r\n";
+#endif
+
+
+PCHAR FW_RED_BANNER_PRESSKEY_MSG = "º Press any key to continue. º";
+
+PCHAR FW_SYSTEM_INCONSISTENCY_WARNING_MSG[] = {
+ "º WARNING: These system areas have problems and may º\r\n",
+ "º prevent Windows NT for Alpha AXP from booting: º\r\n",
+ "º º\r\n"
+};
+
+PCHAR FW_SYSTEM_INCONSISTENCY_WARNING_HOWTOFIX_MSG[] = {
+ "º º\r\n",
+ "º Select \"Set up the system\" from the º\r\n",
+ "º Supplementary menu to correct. º\r\n"
+};
+
+
+//
+// Halt, machine check messages
+//
+
+PCHAR FW_SYSRQ_MONITOR_MSG = "Press SysRq to enter the monitor, press any other key to restart";
+PCHAR FW_FATAL_DMC_MSG = "\r\nFatal system hardware error: double machine check.\r\n\n";
+PCHAR FW_FATAL_MCINPALMODE_MSG = "\r\nFatal system hardware error: machine check in PALmode.\r\n\n";
+PCHAR FW_FATAL_UNKNOWN_MSG = "\r\nUnknown fatal system hardware error.\r\n\n";
+PCHAR FW_FATAL_TAGCNTRL_PE_MSG = "Tag control parity error, Tag control: P: %1x D: %1x S: %1x V: %1x\r\n";
+PCHAR FW_FATAL_TAG_PE_MSG = "Tag parity error, Tag: 0b%17b Parity: %1x\r\n";
+PCHAR FW_FATAL_HEACK_MSG = "Hard error acknowledge: BIU CMD: %x PA: %16Lx\r\n";
+PCHAR FW_FATAL_SEACK_MSG = "Soft error acknowledge: BIU CMD: %x PA: %16Lx\r\n";
+PCHAR FW_FATAL_ECC_ERROR_MSG = "ECC error: %s\r\n";
+PCHAR FW_FATAL_QWLWLW_MSG = "PA: %16Lx Quadword: %x Longword0: %x Longword1: %x\r\n";
+PCHAR FW_FATAL_PE_MSG = "Parity error: %s\r\n";
+PCHAR FW_FATAL_MULTIPLE_EXT_TAG_ERRORS_MSG = "Multiple external/tag errors detected.\r\n";
+PCHAR FW_FATAL_MULTIPLE_FILL_ERRORS_MSG = "Multiple fill errors detected.\r\n";
+
+
+//
+// Menu types
+//
+
+PCHAR FW_MENU_BOOT_MSG = "Boot";
+PCHAR FW_MENU_SUPPLEMENTARY_MSG = "Supplementary";
+PCHAR FW_MENU_SETUP_MSG = "Setup";
+PCHAR FW_MENU_BOOT_SELECTIONS_MSG = "Boot selections";
+
+//
+// Menu strings
+//
+
+PCHAR BootMenuChoices[] = {
+ "Boot the default operating system",
+ "Boot an alternate operating system",
+ "Run a program",
+ "Supplementary menu..."
+};
+
+PCHAR SupplementaryMenuChoices[] = {
+ "Install new firmware",
+ "Install Windows NT from CD-ROM",
+ "Set up the system...",
+ "List available devices",
+ "Execute monitor",
+ "Boot menu..."
+};
+
+PCHAR OperatingSystemSwitchChoices[] = {
+ "Switch to NT",
+ "Switch to OpenVMS",
+ "Switch to OSF",
+ "Setup menu..."
+};
+
+//
+// N.B. This must match the order of MACHINE_PROBLEM.
+//
+
+PCHAR MachineProblemAreas[] = {
+ "None ",
+ "System time ",
+ "Environment variables",
+ "Configuration tree ",
+ "Boot selections ",
+ "",
+ "",
+ "EISA configuration "
+};
+
+
+
+//
+// Error messages
+//
+
+PCHAR FW_ERROR_MSG[] = {
+ "Argument list is too long",
+ "Access violation",
+ "Resource temporarily unavailable",
+ "Bad image file type",
+ "Device is busy",
+ "Fault occured",
+ "Invalid argument",
+ "Device error",
+ "File is a directory",
+ "Too many open files",
+ "Too many links",
+ "Name is too long",
+ "Bad device name/number or partition number",
+ "No such file or directory",
+ "Execute format error",
+ "Not enough memory",
+ "No space left on device",
+ "File is not a directory",
+ "Inappropriate directory path or control operation",
+ "Media not loaded",
+ "Read-only file system"
+};
+
+//
+// Monitor Strings.
+//
+
+PCHAR MON_INVALID_ARGUMENT_COUNT_MSG = "Invalid number of arguments.\r\n";
+PCHAR MON_UNALIGNED_ADDRESS_MSG = "Unaligned address.\r\n";
+PCHAR MON_INVALID_VALUE_MSG = " is not a valid value.\r\n";
+PCHAR MON_INVALID_REGISTER_MSG = " is not a valid register name.\r\n";
+PCHAR MON_BAD_IO_OPERATION_MSG = "Bad I/O operation data size.\r\n";
+PCHAR MON_NOT_VALID_ADDRESS_MSG = " is not a valid address.\r\n";
+PCHAR MON_INVALID_ADDRESS_RANGE_MSG = "Invalid address range.\r\n";
+PCHAR MON_AVAILABLE_HW_DEVICES_MSG = "Available hardware devices:\r\n\n";
+PCHAR MON_MONITOR_MSG = "\r\nNT firmware Monitor.\r\n";
+PCHAR MON_PRESS_H_MSG = "Press H for help, Q to quit.\r\n";
+PCHAR MON_EXCEPTION_MSG = " occurred.\r\n";
+PCHAR MON_NO_RETURN_MSG = "No place to return.\r\n";
+PCHAR MON_RESET_MACHINE_MSG = "Reset the machine? ";
+PCHAR MON_UNRECOGNIZED_COMMAND_MSG = "Unrecognized command.\r\n";
+
+PCHAR MON_HELP_TABLE[] = {
+ "Cmnd Args Operation",
+ "de[bwlq] #1 #2 deposit #2 into \(#1\)",
+ "ex[bwlq] # examine",
+ "d[bwlq] [# [#]] dump bytes/words/longs/quads",
+ "e[bwlq] [# [#]] query deposit",
+ " \(value, sp=next loc, -=prev loc, crlf=exit enter\)",
+ "h this text",
+ "ior[bwl] # I/O space read",
+ "ir, fr dump integer or fp registers",
+ "r id dump the specified register",
+ "z #1 [#2] #1 to #2, or #1 to #1+128",
+ "z #1 l #2 #1 to #1+#2",
+ "f repeated fill with <= 16 values, same args as z.",
+ "q leave monitor\n",
+ "# = @reg|address. enter = do last command for next 128 locs.",
+ "addresses are 32 bit superpage physical."
+};
+
+//
+// Selftest module strings.
+//
+
+PCHAR ST_ALL_IO_TO_SERIAL_LINES_MSG = "Error on keyboard controller or keyboard initialization.\r\nAll I/O will go to the serial ports.\r\n";
+PCHAR ST_BAD_PAGE_SIZE_MSG = "? Bad page size: 0x%x\r\n";
+PCHAR ST_BAD_MEMORY_SIZE_MSG = "? Bad memory size: 0x%x\r\n";
+PCHAR ST_BAD_CLOCK_PERIOD_MSG = "? Bad (zero) cycle clock period.\r\n Clock cycle forced to %d.\r\n";
+PCHAR ST_EISA_ISP_ERROR_MSG = "EISA ISP error.\r\n";
+PCHAR FW_ARC_MULTIBOOT_MSG = " ARC Multiboot DEC Version %s\r\n";
+PCHAR FW_COPYRIGHT_MSG = " Copyright (c) 1993 Microsoft Corporation\r\n Copyright (c) 1993 Digital Equipment Corporation\r\n\n";
+
+
+//
+// FailSafe Booter strings. If necessary, this could be an entirely
+// separate message file to conserve space.
+//
+
+PCHAR FSB_MSG = " DEC FailSafe Booter, Version %s\r\n";
+PCHAR FSB_WHY_RUNNING_MSG = " This is running because an update to your system firmware was\r\n interrupted.\r\n\n";
+PCHAR FSB_FIELD_SERVICE_MSG = " ** If you were not just attempting a firmware update, contact\r\n ** your Digital Field Service representative!\r\n\n";
+PCHAR FSB_LOOKING_FOR_MSG = " Looking for eisa()disk()fdisk()jnupdate.exe...\r\n";
+PCHAR FSB_UPGRADE_ABORTED_MSG = ", upgrade aborted.";
+PCHAR FSB_POWER_CYCLE_TO_REBOOT_MSG = "\r\nPower cycle your system to reboot.";
+
+
+//
+// Stubs strings.
+//
+
+PCHAR ST_RESERVED_ROUTINE_MSG = "ERROR: Unimplemented or reserved routine was called.\r\n";
+PCHAR ST_STACK_UNDERFLOW_1_MSG = "\r\n\n************\r\n************\r\n? Internal Firmware Error!!\r\n Reason: STACK UNDERFLOW\r\n\n";
+PCHAR ST_STACK_UNDERFLOW_2_MSG = "Caller = %x, Caller of the Caller = %x\r\n";
+PCHAR ST_STACK_UNDERFLOW_3_MSG = "Requested area = %x, Stack bottom = %x\r\n\n";
+PCHAR ST_HIT_KEY_FOR_MONITOR_MSG = "Hit any key to jump to the Monitor...\r\n";
+PCHAR ST_BUGCHECK_MSG = "\r\n*** BugCheck (%lx) ***\n\n";
+PCHAR ST_ASSERT_MSG = "\r\n*** Assertion failed ***\r\n";
+PCHAR ST_HIT_KEY_FOR_REBOOT_MSG = "*** Press any key to reboot the system ***\r\n";
+
+
+//
+// Strings used by the built-in system setup utility. These came from
+// jzusa.c
+//
+
+//
+// Prompt strings.
+//
+
+PCHAR SS_TOO_MANY_BOOT_SELECTIONS = " Too many boot selections, delete some before adding another.\r\n";
+PCHAR SS_COUNTDOWN_MSG = " Enter Countdown value (in seconds): ";
+PCHAR SS_OSLOADER_MSG = " Enter the osloader directory and name: ";
+PCHAR SS_OS_MSG = " Is the operating system in the same partition as the osloader: ";
+PCHAR SS_OS_ROOT_MSG = " Enter the operating system root directory: ";
+PCHAR SS_BOOT_NAME_MSG = " Enter a name for this boot selection: ";
+PCHAR SS_INIT_DEBUG_MSG = " Do you want to initialize the debugger at boot time: ";
+PCHAR SS_CANT_SET_VARIABLE_MSG = "Can't set an environment variable\r\n";
+PCHAR SS_NO_SELECTIONS_TO_DELETE_MSG = " No selections to delete, ";
+PCHAR SS_SELECTION_TO_DELETE_MSG = " Selection to delete: ";
+PCHAR SS_ENVIR_FOR_BOOT_MSG = "\r\n Environment variables for boot selection %d:\r\n";
+PCHAR SS_FORMAT1_MSG = " %s\r\n";
+PCHAR SS_USE_ARROWS_MSG = " Use Arrow keys to select a variable, ESC to exit: ";
+PCHAR SS_NO_SELECTIONS_TO_EDIT_MSG = " No selections to edit, ";
+PCHAR SS_SELECTION_TO_EDIT_MSG = " Selection to edit: ";
+PCHAR SS_NO_SELECTIONS_TO_REARRANGE_MSG = " No selections to rearrange, ";
+PCHAR SS_PICK_SELECTION_MSG = " Pick selection to move to the top, ESC to exit: ";
+PCHAR SS_SHOULD_AUTOBOOT_MSG = " Should the system autoboot: ";
+PCHAR SS_ENVIRONMENT_VARS_MSG = " Environment variables:\r\n";
+PCHAR SS_CHECKING_MSG = " Checking ";
+PCHAR SS_CHECKING_BOOT_SEL_NUMBER_MSG = "boot selection number %d...";
+PCHAR SS_FORMAT2_MSG = "%s...";
+PCHAR SS_VARIABLE_NULL_MSG = " %s variable is NULL\r\n";
+PCHAR SS_CANT_BE_FOUND_MSG = " %s cannot be found, value is:\r\n";
+PCHAR SS_PROBLEMS_FOUND_MSG = " Problems were found with ";
+PCHAR SS_PROBLEMS_CHOOSE_AN_ACTION_MSG = " Choose an action:";
+PCHAR SS_SELECTION_MENU_MSG = " %s menu:\r\n";
+PCHAR SS_ECU_WILL_NOW_REBOOT_MSG = "\n This machine will now reboot. Make sure there is an ECU floppy\r\n in the floppy drive.\r\n";
+
+#ifdef ISA_PLATFORM
+PCHAR SS_RESET_TO_FACTORY_DEFAULTS_WARNING_MSG = "This command will overwrite the environment, configuration, and\r\nboot selections with new information.";
+#else
+PCHAR SS_RESET_TO_FACTORY_DEFAULTS_WARNING_MSG = "This command will overwrite the environment, configuration, and\r\nboot selections with new information. You will have to re-execute\r\nthe EISA configuration utility.";
+#endif
+
+PCHAR SS_ARE_YOU_SURE_MSG = "Are you sure you want to do this?";
+PCHAR SS_ESCAPE_FROM_SETUP_MSG = "ESCape from Setup menu...\r\n\nPress ESCape again to abort the changes.\r\nPress Return to save the changes.";
+PCHAR SS_PRESS_KEY_MSG = " Press any key to continue...\r\n";
+PCHAR SS_PRESS_KEY2_MSG = ", press any key to continue";
+PCHAR SS_NAME_MSG = "Name: ";
+PCHAR SS_VALUE_MSG = "Value: ";
+PCHAR SS_NO_NVRAM_SPACE_MSG = "Error: No space in the ROM for this variable";
+PCHAR SS_NVRAM_CHKSUM_MSG = "Error: The ROM checksum is invalid";
+PCHAR SS_ROM_UPDATE_IN_PROGRESS_MSG = " ROM update in progress. Please wait.\r\n";
+PCHAR SS_ROM_UPDATE_FAILED_MSG = "\r\n ERROR: ROM update failed! Your changes may not have been saved.\r\n\n Error info:\r\n";
+PCHAR SS_SELECT_MEDIA_MSG = " Select media: ";
+
+#ifdef ISA_PLATFORM
+PCHAR SS_SELECT_MONITOR_RESOLUTION_MSG = " Select monitor resolution: ";
+#endif
+
+PCHAR SS_ENTER_FAT_OR_NTFS_PART_MSG = " Enter partition (must be FAT or NTFS): ";
+PCHAR SS_ENTER_PART_MSG = " Enter partition: ";
+PCHAR SS_SELECT_SYS_PART_MSG = " Select a system partition for this boot selection:";
+PCHAR SS_SCSI_HD_MSG = "Scsi Hard Disk %1d Partition %1d";
+PCHAR SS_FL_MSG = "Floppy Disk %1d";
+PCHAR SS_SCSI_CD_MSG = "Scsi CD-ROM %1d";
+PCHAR SS_NEW_SYS_PART_MSG = "New system partition";
+PCHAR SS_LOCATE_SYS_PART_MSG = " Enter location of system partition for this boot selection: ";
+PCHAR SS_ENTER_SCSI_ID_MSG = " Enter SCSI ID: ";
+PCHAR SS_ENTER_FLOPPY_DRIVE_NUMBER_MSG = " Enter floppy drive number: ";
+PCHAR SS_LOCATE_OS_PART_MSG = " Enter location of os partition: ";
+PCHAR SS_FLOPPY_SIZE_MSG = " Select floppy drive capacity: ";
+PCHAR SS_2ND_FLOPPY_MSG = " Is there a second floppy: ";
+
+#ifdef ISA_PLATFORM
+PCHAR SS_SCSI_HOST_MSG = " Enter SCSI Host ID (0 - 7): ";
+#endif
+
+PCHAR SS_DEFAULT_SYS_PART_MSG = " Enter location of default system partition:";
+PCHAR SS_ENTER_DATE_MSG = "Enter the new date (mm-dd-yy) : ";
+PCHAR SS_ENTER_TIME_MSG = "Enter time (hh:mm:ss) : ";
+PCHAR SS_ILLEGAL_TIME_MSG = "Illegal time value";
+PCHAR SS_PM = "PM";
+PCHAR SS_AM = "AM";
+PCHAR SS_WHICH_OS_QUERY_MSG = "Which operating system console should be launched at the next power-cycle?\r\n\n";
+PCHAR SS_BOOT_SELECTION_IS_MSG = "Boot selection is currently %s.\r\n";
+PCHAR SS_POWER_CYCLE_FOR_NEW_OS_MSG = "Power-cycle the system to implement the change.\r\nOr, return to this menu to change the selection.\r\n\n";
+
+
+PCHAR SETUP_HELP_TABLE[] = {
+ "Do the following steps, in this order, to set up the system:",
+ "",
+ "1. Set system time.",
+ "2. Set default environment variables.",
+ "3. Set default configuration.",
+ "4. Create at least one boot selection.",
+ "5. Setup autoboot, if desired.",
+#ifdef EISA_PLATFORM
+ "6. Run the EISA configuration utility.",
+#else
+ "",
+#endif
+ "",
+ "-> An arrow next to a menu item means that something is wrong in this",
+ "area of the machine, and you should select this item to fix it.",
+ "",
+ "\"Reset system to factory defaults\" does steps 2 -- 5 for a typical system.",
+ "",
+ "The ESCape key returns from a menu, and aborts a sequence.",
+ "",
+ "The firmware automatically reboots if the configuration is changed.",
+ ""
+};
+
+//
+// Setup Menus.
+//
+
+PCHAR ProblemChoices[] = {
+ "Ignore problems with this boot selection",
+ "Delete this boot selection",
+ "Change this boot selection"
+};
+
+PCHAR YesNoChoices[] = {
+ "Yes",
+ "No"
+};
+
+PCHAR MediaChoices[] = {
+ "Scsi Hard Disk",
+ "Floppy Disk",
+ "CD-ROM"
+};
+
+PCHAR ManageBootSelectionChoices[] = {
+ "Add a boot selection",
+ "Change a boot selection",
+ "Check boot selections",
+ "Delete a boot selection",
+ "Dump boot selections",
+ "Rearrange boot selections",
+ "Setup menu..."
+};
+
+#ifdef ISA_PLATFORM
+PCHAR ResolutionChoices[] = {
+ "1280x1024",
+ "1024x768",
+ "800x600",
+ "640x480"
+};
+#endif
+
+PCHAR FloppyChoices[] = {
+ "5.25\" 1.2MB",
+ "3.5\" 1.44MB",
+ "3.5\" 2.88MB"
+};
+
+PCHAR Weekday[] = {
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+ };
+
+PCHAR SetupMenuChoices[] = {
+ " Set system time",
+ " Set default environment variables",
+ " Set default configuration",
+ " Manage boot selections...",
+ " Setup autoboot",
+ "",
+#ifdef ISA_PLATFORM
+ "",
+#else
+ " Run EISA configuration utility from floppy",
+#endif
+ " Edit environment variables",
+ " Reset system to factory defaults",
+ "",
+ " Help",
+ " Switch to OpenVMS or OSF console",
+ " Supplementary menu, and do not save changes...",
+ " Supplementary menu, and save changes..."
+ };
+
+PCHAR OperatingSystemNames[] = {
+ "NT",
+ "OpenVMS",
+ "OSF"
+};
diff --git a/private/ntos/fw/alpha/inc.h b/private/ntos/fw/alpha/inc.h
new file mode 100644
index 000000000..5b88e0559
--- /dev/null
+++ b/private/ntos/fw/alpha/inc.h
@@ -0,0 +1,908 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ inc.h
+
+Abstract:
+
+ Definitions needed for firmware EISA configuration code.
+
+Author:
+
+ ??
+
+Revision History:
+
+ 3-December-1992 John DeRosa [DEC]
+
+ Alpha/Jensen modifications.
+
+--*/
+
+
+///////////////////////////////////////////////////////////////////////////////
+// General definitions
+///////////////////////////////////////////////////////////////////////////////
+
+
+#define WORD_2P2 2 // 2^2 = 4 bytes
+#define HALFWORD_2P2 1 // 2^1 = 2 bytes
+#define BYTE_2P2 0 // 2^0 = 1 bytes
+#define BITSXBYTE 8 // 8 bits = 1 byte
+
+#define ASCII_BLOCK_SIZE 512 // ASCII block size
+
+#define MIN(x,y) ((x) > (y) ? (y) : (x)) // minimum number
+
+
+#define INSTRUCTION_DELAY 10 // nsec for each instruction
+ // using 50MHZ externl clock
+#define MAX_DCACHE_LINE_SIZE 32 // max bytes per Data cache line
+
+#define UNMAPPED_SIZE (512*1024*1024) // 512 Mbytes of unmapped space
+
+#define PAGE_4G_SHIFT 32 // 2^32 = 4Gbytes
+#define PAGE_32M_SHIFT 25 // 2^25 = 32Mbytes
+#define PAGE_32M_SIZE (1 << PAGE_32M_SHIFT) // 32 Mbytes
+#define PAGE_16M_SHIFT 24 // 2^24 = 16Mbytes
+#define PAGE_16M_SIZE (1 << PAGE_16M_SHIFT) // 16 Mbytes
+#define PAGE_8M_SHIFT 23 // 2^23 = 8Mbytes
+#define PAGE_8M_SIZE (1 << PAGE_8M_SHIFT) // 8 Mbytes
+#define PAGE_4M_SHIFT 22 // 2^22 = 4Mbytes
+#define PAGE_4M_SIZE (1 << PAGE_4M_SHIFT) // 4 Mbytes
+#define PAGE_2M_SHIFT 21 // 2^21 = 2Mbytes
+#define PAGE_2M_SIZE (1 << PAGE_2M_SHIFT) // 2 Mbytes
+#define PAGE_1M_SHIFT 20 // 2^20 = 1Mbyte
+#define PAGE_1M_SIZE (1 << PAGE_1M_SHIFT) // 1 Mbyte
+#define PAGE_MAX_SHIFT PAGE_16M_SHIFT // max TLB page shift.
+#define PAGE_MAX_SIZE (1 << PAGE_MAX_SHIFT) // max TLB page (one entry)
+#define PAGES_IN_4G (1 << (PAGE_4G_SHIFT - PAGE_SHIFT)) // # 4k in 4Gbytes
+#define PAGES_IN_16M (1 << (PAGE_16M_SHIFT - PAGE_SHIFT)) // # 4k in 16Mbytes
+#define PAGES_IN_1M (1 << (PAGE_1M_SHIFT - PAGE_SHIFT)) // # 4k in 1Mbyte
+
+//#define HIT_WRITEBACK_D 0x19 // hit write back 1st cache
+//#define HIT_WRITEBACK_SD 0x1B // hit write back 2nd cache
+
+#define EISA_LATCH_VIRTUAL_BASE (DEVICE_VIRTUAL_BASE + 0xE000)
+#define EISA_LOCK_VIRTUAL_BASE (DEVICE_VIRTUAL_BASE + 0xE800)
+#define EISA_INT_ACK_ADDR (DEVICE_VIRTUAL_BASE + 0x238)
+#define INT_ENABLE_ADDR (DEVICE_VIRTUAL_BASE + 0xE8)
+
+//
+// coff image info structure
+//
+
+typedef struct _IMAGE_FLAGS
+ {
+ ULONG Exec : 1;
+ ULONG Reloc : 1;
+
+ } IMAGE_FLAGS, *PIMAGE_FLAGS;
+
+
+typedef struct _IMAGE_INFO
+ {
+ IMAGE_FLAGS Flags; // image characteristic
+ ULONG ImageBase; // base address
+ ULONG ImageSize; // in 4k units
+
+ } IMAGE_INFO, *PIMAGE_INFO;
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+// General function prototypes
+///////////////////////////////////////////////////////////////////////////////
+
+PCHAR
+FwToUpperStr
+ (
+ IN OUT PCHAR s
+ );
+
+PCHAR
+FwToLowerStr
+ (
+ IN OUT PCHAR s
+ );
+
+PCHAR
+FwGetPath
+ (
+ IN PCONFIGURATION_COMPONENT Component,
+ OUT PCHAR String
+ );
+
+PCHAR
+FwGetMnemonic
+ (
+ IN PCONFIGURATION_COMPONENT Component
+ );
+
+BOOLEAN
+FwValidMnem
+ (
+ IN PCHAR Str
+ );
+
+ULONG
+Fw4UcharToUlongLSB
+ (
+ IN PUCHAR String
+ );
+
+
+ULONG
+Fw4UcharToUlongMSB
+ (
+ IN PUCHAR String
+ );
+
+PCHAR
+FwStoreStr
+ (
+ IN PCHAR Str
+ );
+
+BOOLEAN
+FwGetNumMnemonicKey
+ (
+ IN PCHAR Path,
+ IN UCHAR KeyNumber,
+ IN PULONG Key
+ );
+
+BOOLEAN
+FwGetMnemonicKey
+ (
+ IN PCHAR Path,
+ IN PCHAR Mnemonic,
+ IN PULONG Key
+ );
+
+BOOLEAN
+FwGetNextMnemonic
+ (
+ IN PCHAR Path,
+ IN PCHAR Mnemonic,
+ OUT PCHAR NextMnemonic
+ );
+
+BOOLEAN
+FwGetMnemonicPath
+ (
+ IN PCHAR Path,
+ IN PCHAR Mnemonic,
+ OUT PCHAR MnemonicPath
+ );
+
+BOOLEAN
+FwGetEisaId
+ (
+ IN PCHAR PathName,
+ OUT PCHAR EisaId,
+ OUT PUCHAR IdInfo
+ );
+
+VOID
+FwUncompressEisaId
+ (
+ IN PUCHAR CompEisaId,
+ OUT PUCHAR UncompEisaId
+ );
+
+BOOLEAN
+FwGetEisaBusIoCpuAddress
+ (
+ IN PCHAR EisaPath,
+ OUT PVOID *IoBusAddress
+ );
+
+BOOLEAN
+GetNextPath
+ (
+ IN OUT PCHAR *PPathList,
+ OUT PCHAR PathTarget
+ );
+
+//PDRIVER_STRATEGY
+//FwGetStrategy
+// (
+// IN PCHAR Path
+// );
+
+ARC_STATUS
+FwGetImageInfo
+ (
+ IN PCHAR ImagePath,
+ OUT PIMAGE_INFO pImageInfo
+ );
+
+PCONFIGURATION_COMPONENT
+FwGetControllerComponent
+ (
+ IN PCHAR Path
+ );
+
+PCONFIGURATION_COMPONENT
+FwGetPeripheralComponent
+ (
+ IN PCHAR Path
+ );
+
+PCHAR
+FwGetControllerMnemonic
+ (
+ IN PCHAR Path
+ );
+
+PCHAR
+FwGetPeripheralMnemonic
+ (
+ IN PCHAR Path
+ );
+
+BOOLEAN
+FwSizeToShift
+ (
+ IN ULONG Size,
+ OUT ULONG Shift
+ );
+
+ARC_STATUS
+FwGetImageInfo
+ (
+ IN PCHAR ImagePath,
+ OUT PIMAGE_INFO pImageInfo
+ );
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+// EISA configuration
+///////////////////////////////////////////////////////////////////////////////
+
+
+
+#define NO_ADAP_ID 0x80000000 // adapter id not present
+#define WAIT_ADAP_ID 0x70000000 // adapter not ready yet
+#define TIMEOUT_UNITS 200 // 200 units of 10msec
+
+
+typedef struct _EISA_SLOT_INFO
+ {
+ UCHAR IdInfo;
+ UCHAR MajorRevLevel;
+ UCHAR MinorRevLevel;
+ UCHAR LSByteChecksum;
+ UCHAR MSByteChecksum;
+ UCHAR FunctionsNumber;
+ UCHAR FunctionInfo;
+ UCHAR Id1stChar;
+ UCHAR Id2ndChar;
+ UCHAR Id3rdChar;
+ UCHAR Id4thChar;
+ } EISA_SLOT_INFO, *PEISA_SLOT_INFO;
+
+
+#define ID_DIGIT_SIZE 4 // # of bits
+#define ID_CHAR_SIZE 5 // # of bits
+#define ID_DIGIT_MASK ((1<<ID_DIGIT_SIZE)-1) // field size
+#define ID_CHAR_MASK ((1<<ID_CHAR_SIZE)-1) // field size
+#define EISA_SLOT_INFO_SIZE sizeof(EISA_SLOT_INFO)
+#define EISA_FUNC_INFO_SIZE 320 // fixed length
+
+#define EISA_SLOT_MIN_INFO ( CONFIGDATAHEADER_SIZE + EISA_SLOT_INFO_SIZE )
+
+//
+// EISA configuration data extensions
+//
+
+typedef struct _EISA_ADAPTER_DETAILS
+ {
+ CONFIGDATAHEADER ConfigDataHeader;
+ ULONG NumberOfSlots;
+ PVOID IoStart;
+ ULONG IoSize;
+ } EISA_ADAPTER_DETAILS, *PEISA_ADAPTER_DETAILS;
+
+
+
+//
+// EISA_FUNC_INFO block offsets
+//
+
+#define CFG_ID_INFO_OFS 0x04 // offset to Id info byte
+#define CFG_SLOT_INFO_OFS 0x05 // offset to slot info byte
+#define CFG_FN_INFO_OFS 0x22 // offset to function info byte
+#define CFG_ASC_BLK_OFS 0x23 // offset to ASCII data block
+#define CFG_MEM_BLK_OFS 0x73 // offset to mem cfg data block
+#define CFG_IRQ_BLK_OFS 0xB2 // offset to IRQ cfg data block
+#define CFG_DMA_BLK_OFS 0xC0 // offset to DMA cfg data block
+#define CFG_PRT_BLK_OFS 0xC8 // offset to port I/O data block
+#define CFG_INI_BLK_OFS 0x104 // offset to port init data block
+
+#define CFG_FREE_BLK_OFS 0x73 // offset of free form cfg data block
+
+//
+// EISA_FUNC_INFO block lengths
+//
+
+#define CFG_ASC_BLK_LEN 80 // length of ASCII data block
+#define CFG_MEM_BLK_LEN 63 // length of mem cfg data block
+#define CFG_IRQ_BLK_LEN 14 // length of IRQ cfg data block
+#define CFG_DMA_BLK_LEN 8 // length of DMA cfg data block
+#define CFG_PRT_BLK_LEN 60 // length of port I/O data block
+#define CFG_INI_BLK_LEN 60 // length of port init data block
+
+#define CFG_FREE_BLK_LEN 205 // length of free form cfg data block
+
+//
+// ID info byte layout
+//
+
+#define CFG_DUPLICATE_ID 0x80 // more IDs with the same value
+#define CFG_UNREADABLE_ID 0x40 // the ID is not readable
+#define CFG_SLOT_MASK 0x30 // slot mask
+#define CFG_SLOT_EXP 0x00 // expansion slot
+#define CFG_SLOT_EMB 0x10 // embedded slot
+#define CFG_SLOT_VIR 0x20 // virtual slot
+
+//
+// slot info byte layout
+//
+
+#define CFG_INCOMPLETE 0x80 // configuration is incomplete
+#define CFG_EISA_IOCHKERR 0x02 // support for EISA IOCHKERR signal
+#define CFG_EISA_ENABLE 0x01 // support for disable feature
+
+//
+// function information byte layout
+//
+
+#define CFG_FN_DISABLED 0x80 // function is disabled
+#define CFG_FREE_FORM 0x40 // free-form data
+#define CFG_INI_ENTRY 0x20 // port init entry(s) exists
+#define CFG_PRT_ENTRY 0x10 // port range entry(s) exists
+#define CFG_DMA_ENTRY 0x08 // DMA entry(s) exists
+#define CFG_IRQ_ENTRY 0x04 // IRQ entry(s) exists
+#define CFG_MEM_ENTRY 0x02 // memory entry(s) exists
+#define CFG_ASC_ENTRY 0x01 // type/subtype entry follows
+
+#define CFG_MORE_ENTRY 0x80 // more mem/DMA/int/port entries
+
+//
+// memory configuration byte layout
+//
+
+#define CFG_MEM_RW 0x01 // memory is read/write
+#define CFG_MEM_CACHE 0x02 // enable caching of memory
+#define CFG_MEM_WRBACK 0x04 // cache is write-back
+#define CFG_MEM_TYPE 0x18 // memory type mask
+#define CFG_MEM_SYS 0x00 // base or extended
+#define CFG_MEM_EXP 0x08 // expanded
+#define CFG_MEM_VIR 0x10 // virtual
+#define CFG_MEM_OTHER 0x18 // other
+
+//
+// interrupt configuration byte layout
+//
+
+#define CFG_IRQ_SHARE 0x40 // IRQ is sharable
+#define CFG_IRQ_LEVEL 0x20 // IRQ is level triggered
+#define CFG_IRQ_MASK 0x0F // IRQ mask
+
+//
+// DMA configuration byte layout
+//
+
+#define CFG_DMA_SHARED 0x40 // DMA has to be chared
+#define CFG_DMA_MASK 0x07 // DMA mask
+#define CFG_DMA_CFG_MASK 0x3C // used to mask off the reserved bits
+#define CFG_DMA_TIM_MASK 0x30 // timing mode bits mask
+#define CFG_DMA_ADD_MASK 0x0C // addressing mode bits mask
+
+//
+// init configuration byte layout
+//
+
+#define CFG_INI_PMASK 0x04 // Port value or port and mask value
+#define CFG_INI_MASK 0x03 // Type of access (byte, word or dword)
+#define CFG_INI_BYTE 0x00 // Byte address (8-bit)
+#define CFG_INI_HWORD 0x01 // HalfWord address (16-bit)
+#define CFG_INI_WORD 0x02 // Word address (32-bit)
+
+
+//
+// eisa cfg errors
+//
+
+typedef enum _EISA_CFG_ERROR
+ {
+ CfgNoErrCode,
+ IdTimeout,
+ CfgIdError,
+ CfgMissing,
+ CfgIncomplete,
+ CfgIncorrect,
+ CfgDeviceFailed,
+ CfgMemError,
+ CfgIrqError,
+ CfgDmaError,
+ CfgIniError,
+ OmfRomError,
+ OmfError,
+ MemAllocError,
+ TooManyDeviceError,
+ BufferMarkError,
+ MaximumValue
+ } EISA_CFG_ERROR;
+
+
+//
+// eisa pod messages index
+//
+
+typedef enum _EISA_CHECKPOINT
+ {
+ EisaPic,
+ EisaDma,
+ EisaNmi,
+ EisaRefresh,
+ EisaPort61,
+ EisaTimer1,
+ EisaTimer2,
+ EisaCfg,
+ EisaHotNmi,
+ EisaPodMaxMsg
+
+ } EISA_CHECKPOINT;
+
+//
+// define pod structure
+//
+
+typedef struct _EISA_CHECKPOINT_INFO
+ {
+ PCHAR Msg; // pod message
+ UCHAR Flags; // control flags
+ // bit 0 = error
+ // bit 1 = fatal
+ // bit 2 = configuration
+ // bit 3 = display pass/error message
+ UCHAR Par; // PARALLEL test number
+ UCHAR SubPar; // PARALLEL subtest number
+ UCHAR Led; // LED test number
+ UCHAR SubLed; // LED subtest number
+
+ } EISA_CHECKPOINT_INFO, *PEISA_CHECKPOINT_INFO;
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+// EISA I/O ports
+///////////////////////////////////////////////////////////////////////////////
+
+//
+// PIC
+//
+
+#define PIC1 0x20 // 1st PIC address (0-7 IRQs)
+#define PIC1_MASK 0x21 // 1st PIC mask port (0-7 IRQs)
+#define PIC1_ELCR 0x4D0 // 1st Edge/Level Control Register
+
+#define PIC2 0xA0 // 2nd PIC address (8-15 IRQs)
+#define PIC2_MASK 0xA1 // 2nd PIC mask port (8-15 IRQs)
+#define PIC2_ELCR 0x4D1 // 2nd Edge/Level Control Register
+
+#define EISA_IRQS 16 // # IRQ lines
+
+#define IRQ0 0x00 // 1st IRQ (1st PIC)
+#define IRQ1 0x01 // 2nd IRQ (1st PIC)
+#define IRQ2 0x02 // 3th IRQ (1st PIC)
+#define IRQ3 0x03 // 4th IRQ (1st PIC)
+#define IRQ4 0x04 // 5th IRQ (1st PIC)
+#define IRQ5 0x05 // 6th IRQ (1st PIC)
+#define IRQ6 0x06 // 7th IRQ (1st PIC)
+#define IRQ7 0x07 // 8th IRQ (1st PIC)
+#define IRQ8 0x08 // 9th IRQ (2nd PIC)
+#define IRQ9 0x09 // 10th IRQ (2nd PIC)
+#define IRQ10 0x0A // 11th IRQ (2nd PIC)
+#define IRQ11 0x0B // 12th IRQ (2nd PIC)
+#define IRQ12 0x0C // 13th IRQ (2nd PIC)
+#define IRQ13 0x0D // 14th IRQ (2nd PIC)
+#define IRQ14 0x0E // 15th IRQ (2nd PIC)
+#define IRQ15 0x0F // 16th IRQ (2nd PIC)
+
+#define OCW3_IRR 0x0A // OCW3 command to read the IRR
+#define OCW3_ISR 0x0B // OCW3 command to read the ISR
+#define OCW2_EOI 0x20 // OCW2 non specific EOI
+#define OCW2_SEOI 0x60 // OCW2 specific EOI mask
+
+
+
+//
+// DMA
+//
+
+
+#define EISA_DMAS 8 // # of DMA channels
+
+#define DMA_COUNT_0 0x01 // 16-bit count register
+#define DMA_COUNT_1 0x03 // 16-bit count register
+#define DMA_COUNT_2 0x05 // 16-bit count register
+#define DMA_COUNT_3 0x07 // 16-bit count register
+#define DMA_COUNT_4 0x0C2 // 16-bit count register
+#define DMA_COUNT_5 0x0C6 // 16-bit count register
+#define DMA_COUNT_6 0x0CA // 16-bit count register
+#define DMA_COUNT_7 0x0CE // 16-bit count register
+
+#define DMA_HCOUNT_0 0x0401 // I/O address high word count reg.
+#define DMA_HCOUNT_1 0x0403 // I/O address high word count reg.
+#define DMA_HCOUNT_2 0x0405 // I/O address high word count reg.
+#define DMA_HCOUNT_3 0x0407 // I/O address high word count reg.
+#define DMA_HCOUNT_5 0x04C6 // I/O address high word count reg.
+#define DMA_HCOUNT_6 0x04CA // I/O address high word count reg.
+#define DMA_HCOUNT_7 0x04CE // I/O address high word count reg.
+
+#define DMA_ADDR_0 0x00 // 16-bit address register
+#define DMA_ADDR_1 0x02 // 16-bit address register
+#define DMA_ADDR_2 0x04 // 16-bit address register
+#define DMA_ADDR_3 0x06 // 16-bit address register
+#define DMA_ADDR_4 0x0C0 // 16-bit address register
+#define DMA_ADDR_5 0x0C4 // 16-bit address register
+#define DMA_ADDR_6 0x0C8 // 16-bit address register
+#define DMA_ADDR_7 0x0CC // 16-bit address register
+
+#define DMA_PAGE_0 0x087 // 8-bit address, low page
+#define DMA_PAGE_1 0x083 // 8-bit address, low page
+#define DMA_PAGE_2 0x081 // 8-bit address, low page
+#define DMA_PAGE_3 0x082 // 8-bit address, low page
+#define DMA_PAGE_RFR 0x08F // DMA lo page register refresh
+#define DMA_PAGE_5 0x08B // 8-bit address, low page
+#define DMA_PAGE_6 0x089 // 8-bit address, low page
+#define DMA_PAGE_7 0x08A // 8-bit address, low page
+
+#define DMA_HPAGE_0 0x0487 // I/O address, high page
+#define DMA_HPAGE_1 0x0483 // I/O address, high page
+#define DMA_HPAGE_2 0x0481 // I/O address, high page
+#define DMA_HPAGE_3 0x0482 // I/O address, high page
+#define DMA_HPAGE_RFR 0x048F // DMA hi page register refresh
+#define DMA_HPAGE_5 0x048B // I/O address, high page
+#define DMA_HPAGE_6 0x0489 // I/O address, high page
+#define DMA_HPAGE_7 0x048A // I/O address, high page
+
+#define DMA_STOP_0 0x04E0 // stop register
+#define DMA_STOP_1 0x04E4 // stop register
+#define DMA_STOP_2 0x04E8 // stop register
+#define DMA_STOP_3 0x04EC // stop register
+#define DMA_STOP_5 0x04F4 // stop register
+#define DMA_STOP_6 0x04F8 // stop register
+#define DMA_STOP_7 0x04FC // stop register
+
+// channels 0 to 3
+
+#define DMA_STATUS03 0x08 // status register
+#define DMA_COMMAND03 0x08 // command register
+#define DMA_REQUEST03 0x09 // request register
+#define DMA_1MASK03 0x0A // set/clear one mask reg
+#define DMA_MODE03 0x0B // 6-bit write mode register
+#define DMA_FF_CLR03 0x0C // clear byte pointer flip/flop
+#define DMA_TEMP 0x0D // 8-bit read temporary register
+#define DMA_MASTER_CLR03 0x0D // master clear reg
+#define DMA_MASK_CLR03 0x0E // clear all mask reg bits
+#define DMA_MASKS03 0x0F // write all mask reg bits
+#define DMA_MASK_STAT03 0x0F // mask status register
+#define DMA_CHAIN03 0x040A // chaining mode register
+#define DMA_EXTMODE03 0x040B // extended mode register
+
+// channels 4 to 7
+
+#define DMA_STATUS47 0x0D0 // status register
+#define DMA_COMMAND47 0x0D0 // command register
+#define DMA_REQUEST47 0x0D2 // request register
+#define DMA_1MASK47 0x0D4 // set/clear one mask reg
+#define DMA_MODE47 0x0D6 // 6-bit write mode register
+#define DMA_FF_CLR47 0x0D8 // clear byte pointer flip/flop
+#define DMA_MASTER_CLR47 0x0DA // master clear reg
+#define DMA_MASK_CLR47 0x0DC // clear all mask reg bits
+#define DMA_MASKS47 0x0DE // write all mask reg bits
+#define DMA_MASK_STAT47 0x0DE // mask status register
+#define DMA_CHAIN47 0x04D4 // chaining mode register
+#define DMA_EXTMODE47 0x04D6 // extended mode register
+
+typedef struct _EISA_DMA_REGS_TEST
+ {
+ USHORT Address; // address register
+ USHORT LowPage; // low page register
+ USHORT HighPage; // high page register
+ USHORT LowCount; // low count register
+ USHORT HighCount; // high count register
+ USHORT Stop; // stop count register
+
+ } EISA_DMA_REGS_TEST, *PEISA_DMA_REGS_TEST;
+
+typedef struct _EISA_DMA_CTRL_TEST
+ {
+ USHORT Clear; // clear mask register
+ USHORT MaskAll; // set global mask register
+ USHORT Mask; // set single mask register
+ USHORT MaskStatus; // status mask register
+ USHORT Chain; // chaining register
+
+ } EISA_DMA_CTRL_TEST, *PEISA_DMA_CTRL_TEST;
+
+//
+// Option Boards
+//
+
+
+#define EISA_PRODUCT_ID 0xC80 // word
+#define EXPANSION_BOARD_CTRL_BITS 0xC84 // byte
+#define EISA_IOCHKERR 0x02 // IOCHKERR bit
+#define EISAROMBIT 0x08 // ARC ROM bit
+#define ROMINDEX 0xCB0 // word
+#define ROMREAD 0xCB4 // word
+
+
+//
+// General ports
+//
+
+#define EISA_TIMER1_CTRL 0x43 // interval timer1 ctrl port
+#define EISA_TIMER1_COUNTER0 0x40 // timer1 counter 0
+#define EISA_TIMER1_COUNTER1 0x41 // timer1 counter 1
+#define EISA_TIMER1_COUNTER2 0x42 // timer1 counter 2
+#define EISA_RFR_COUNT 0x12 // refresh count ~15usec
+#define EISA_SPEAKER_CLOCK 1193000 // timer1 counter2 clock
+#define EISA_SPEAKER_FREQ 896 // fw speaker frequence in Hz
+#define EISA_SPEAKER_MAX_FREQ EISA_SPEAKER_CLOCK
+#define EISA_SPEAKER_MIN_FREQ (EISA_SPEAKER_CLOCK/0xFFFF + 1)
+
+#define EISA_TIMER2_CTRL 0x4B // interval timer2 ctrl port
+#define EISA_TIMER2_COUNTER0 0x48 // timer2 counter 0
+#define EISA_TIMER2_COUNTER2 0x4A // timer2 counter 2
+
+// the meaning of EISA_RFR_RETRY is as follow :
+// 35usec ( 15usec * 2) = 35*1000 nsec
+// 3 instructions = read, test, jump (the worst case)
+
+#define EISA_RFR_RETRY ((35*1000)/(3*INSTRUCTION_DELAY))
+
+#define EISA_SYS_CTRL_PORTB 0x61 // System Control Port B
+
+#define EISA_SPEAKER_GATE 0x01 // gate signal for speaker timer
+#define EISA_SPEAKER_TIMER 0x02 // speaker timer on
+#define EISA_PARITY_OFF 0x04 // parity error disabled
+#define EISA_IOCHK_OFF 0x08 // I/O channel check disabled
+#define EISA_REFRESH 0x10 // refresh bit ( bit 4 )
+#define EISA_SPEAKER_OUT 0x20 // speaker output
+#define EISA_IOCHK_STATUS 0x40 // IOCHK# asserted
+#define EISA_PARITY_STATUS 0x80 // parity error
+
+#define EISA_RTC_CTRL 0x70 // real time clock address
+#define EISA_DISABLE_NMI 0x80 // disable nmi bit
+#define RTC_A_REG 0x0A // status reg a
+#define RTC_B_REG 0x0B // status reg b
+#define RTC_C_REG 0x0C // status reg c
+#define RTC_D_REG 0x0D // status reg d
+
+#define EISA_SYS_EXT_NMI 0x461 // ext NMI control and bus reset
+#define EISA_SW_NMI_PORT 0x462 // software NMI generation port
+#define EISA_BUSMASTER_LSTATUS 0x464 // 32-bit bus master status low
+#define EISA_BUSMASTER_HSTATUS 0x465 // 32-bit bus master status high
+
+#define EISA_BUS_RESET 0x01 // bus reset asserted bit
+#define EISA_ENABLE_NMI_IO 0x02 // NMI I/O port bit
+#define EISA_ENABLE_NMI_SAFE 0x04 // Fail-safe NMI bit
+#define EISA_ENABLE_NMI_32 0x08 // 32-bit bus timeout
+#define EISA_NMI_32_CAUSE 0x10 // 0=slave 1=bus master timeout
+#define EISA_NMI_IO_STATUS 0x20 // NMI I/O port status bit
+#define EISA_NMI_32_STATUS 0x40 // 32-bit bus timeout
+#define EISA_NMI_SAFE_STATUS 0x80 // Fail-save NMI status bit
+#define EISA_WAIT_NMI_TEST 500 // usec.
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Map Descriptor
+//
+// The following map descriptor is used to describe a specific region in
+// memory mapped through an entry/entries within the TLB (CPU) or within
+// the logical to physical table (bus master).
+///////////////////////////////////////////////////////////////////////////////
+
+
+#define TLB_FW_RES 0x00000020 // 0x20 (even + odd)
+#define TLB_BE_SPT 0x0000001C // TLB entry for the BE SPT
+#define BE_SPT_VIR_ADDR 0x70000000 // BE SPT virtual address
+#define TLB_USER 0x0000001E // user TLB entry (0-based)
+#define USER_VIR_ADDR 0x00000000 // user virtual address
+#define TLB_EISA_START TLB_FW_RES // TLB base for EISA descript.
+#define TLB_EISA_END 0x00000060 // last available TLB + 1
+#define TLB_EISA_NUMB TLB_EISA_END - TLB_EISA_START
+#define EISA_VIR_MEM 0x02000000 // start EISA mem virtual addr.
+#define EISA_MEM_BLOCKS 30 // max memory descriptors
+#define BUS_MASTERS 25 // max bus masters number
+
+#define FW_MD_POOL (BUS_MASTERS + TLB_EISA_NUMB + EISA_MEM_BLOCKS)
+
+
+
+typedef struct _FW_MD_FLAGS
+ {
+ ULONG Busy : 1;
+ } FW_MD_FLAGS, *PFW_MD_FLAGS;
+
+typedef struct _LOG_CONTEXT
+ {
+ ULONG LogAddr; // starting logical address
+ ULONG LogNumb; // # entries to map transfer
+ ULONG LogLimit; // logical limit
+ ULONG LogShift; // page shift (0xC=4k, 2^0xC=4k)
+ PVOID BuffVir; // virtual address buffer
+ } LOG_CONTEXT, *PLOG_CONTEXT;
+
+typedef struct _MEM_CONTEXT
+ {
+ //ULONG BusType; // memory bus type
+ ULONG BusNumber; // key of bus type
+ ULONG SlotNumber; // slot number if applicable
+ ULONG Type; // memory type
+ } MEM_CONTEXT, *PMEM_CONTEXT;
+
+typedef struct _EMEM_CONTEXT
+ {
+ ULONG WinRelAddr; // EISA
+ ULONG WinShift; // window size
+ PVOID WinRelAddrCtrl; // window ctrl port (vir.addr.)
+ } EMEM_CONTEXT, PEMEM_CONTEXT;
+
+typedef struct _FW_MD
+ {
+
+ // general fields
+
+ struct _FW_MD * Link; // next entry
+ FW_MD_FLAGS Flags; // map entry flags
+ ULONG Counter; // # entities sharing this entry
+
+ // physical and virtual address (size of page fixed to 4k)
+
+ ULONG PhysAddr; // physical address (4k)
+ ULONG PagOffs; // page offset (within 4k)
+ PVOID VirAddr; // virtual address
+ ULONG Size; // buffer size in bytes
+ ULONG PagNumb; // buffer in 4k pages
+ BOOLEAN Cache; // cache status
+
+ // private section
+
+ union
+ {
+ LOG_CONTEXT l; // logical context
+ MEM_CONTEXT m; // physical memory context
+ EMEM_CONTEXT em; // EISA memory space
+ } u;
+ } FW_MD, *PFW_MD;
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+// EISA buses defines
+///////////////////////////////////////////////////////////////////////////////
+
+
+#define EISA_BUSES 1 // number of eisa buses
+
+//
+// moved to respective machdef.h file
+//
+//#define PHYS_0_SLOTS 8 // physical slots (max number)
+//
+
+#define VIR_0_SLOTS 16 // virtual slots (max number )
+// NOTE: Wait longer for JAZZ and Jensen.
+//#define EISA_IO_DELAY FwStallExecution(1); // to define !
+#define EISA_IO_DELAY FwStallExecution(4); // to define !
+
+
+// note: the following structs have to be half word aligned
+
+typedef struct _EISA_POD_FLAGS
+ {
+ ULONG IniDone : 1; // POD initialization done
+ ULONG Error : 1; // POD status
+
+ } EISA_POD_FLAGS, *PEISA_POD_FLAGS;
+
+
+typedef struct _EISA_SLOTS_INFO
+ {
+ ULONG PhysSlots; // # of physical slots
+ ULONG VirSlots; // # of virtual slots
+ ULONG SlotCfgMap; // one bit x slot; 1 = slot ok
+
+ } EISA_SLOTS_INFO, *PEISA_SLOTS_INFO;
+
+
+typedef struct _EISA_DMA_FLAGS
+ {
+ UCHAR Busy : 1; // DMA channel busy flag
+ UCHAR Tc : 1; // Terminal count reached
+
+ } EISA_DMA_FLAGS, *PEISA_DMA_FLAGS;
+
+
+typedef struct _EISA_DMA_INFO
+ {
+ EISA_POD_FLAGS Flags; // POD flags
+ EISA_DMA_FLAGS DmaFlags[ EISA_DMAS ]; // DMA status
+ UCHAR DmaExtReg[ EISA_DMAS ]; // DMA extended reg.
+ ULONG TransferAddress[ EISA_DMAS ]; // Logical addresses
+
+ } EISA_DMA_INFO, *PEISA_DMA_INFO;
+
+
+typedef struct _EISA_INT_INFO
+ {
+ EISA_POD_FLAGS Flags; // POD flags
+ USHORT IrqPresent; // IRQ present (1 bit per IRQ)
+ USHORT IrqShareable; // IRQ shareable (1 bit per IRQ)
+ USHORT IrqLevel; // IRQ level (1 bit per IRQ)
+
+ } EISA_INT_INFO, *PEISA_INT_INFO;
+
+
+typedef struct _EISA_PORT_INFO
+ {
+ EISA_POD_FLAGS Flags; // POD flags
+
+ } EISA_PORT_INFO, *PEISA_PORT_INFO;
+
+
+typedef struct _EISA_BUS_INFO
+ {
+ EISA_POD_FLAGS Flags; // Bus Flags
+ PFW_MD IoBusInfo; // EISA I/O bus info
+ PFW_MD MemBusInfo; // EISA memory bus info
+ PEISA_SLOTS_INFO SlotsInfo; // physical slots info
+ PEISA_DMA_INFO DmaInfo; // DMA info struct pointer
+ PEISA_INT_INFO IntInfo; // Interrupts info struct point.
+ PEISA_PORT_INFO PortInfo; // Interrupts info struct point.
+
+ } EISA_BUS_INFO, *PEISA_BUS_INFO;
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+// EISA call back support
+///////////////////////////////////////////////////////////////////////////////
+
+
+#define STATUS_INT_MASK 0x0000FF01 // Hardware Interrupt Mask
+#define STATUS_IE 0x00000001 // Interrupts enable bit
+#define STATUS_SW0 0x00000100 // Software interrupt
+#define STATUS_SW1 0x00000200 // Software interrupt
+#define STATUS_MCT_ADR 0x00000400 // MCT_ADR interrupt
+#define STATUS_DEVICE 0x00000800 // I/O device interrupt
+#define STATUS_EISA 0x00001000 // EISA device interrupt
+#define STATUS_EISA_NMI 0x00002000 // EISA NMI interrupt
+#define STATUS_EX_TIMER 0x00004000 // Interval timer interrupt
+#define STATUS_IN_TIMER 0x00008000 // Internal timer interrupt
+#define EISA_VECTOR 0x04 // EISA device interrupt vector
+#define EISA_NMI_VECTOR 0x05 // EISA NMI interrupt vector
+
+
+
diff --git a/private/ntos/fw/alpha/iodevice.h b/private/ntos/fw/alpha/iodevice.h
new file mode 100644
index 000000000..85c712049
--- /dev/null
+++ b/private/ntos/fw/alpha/iodevice.h
@@ -0,0 +1,258 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ iodevice.h
+
+Abstract:
+
+ This module contains definitions to access the IO devices in the
+ Alpha Jensen system.
+
+Author:
+
+ Lluis Abello (lluis) 03-Jan-1991
+
+Environment:
+
+
+Revision History:
+
+ 21-May-1992 John DeRosa [DEC]
+
+ Modified Lluis's original Jazz file for Alpha/Jensen.
+
+--*/
+
+#ifndef _IODEVICE_
+#define _IODEVICE_
+
+//#include <jnsndef.h>
+//#include <jnsnrtc.h>
+
+#include "machdef.h"
+#include <jnsnserp.h>
+#include <eisa.h> // for the isp interrupt controller init.
+
+
+//
+// Not defined in the Alpha/Jensen firmware. The one place where this was
+// used, the floppy driver, now uses WaitForFloppyInterrupt.
+//
+
+#if 0
+ARC_STATUS
+FwWaitForDeviceInterrupt(
+ USHORT InterruptMask,
+ ULONG Timeout
+ );
+#endif // 0
+
+
+
+//
+// HAE and SYSCTL structure, values, and pointers.
+//
+
+typedef struct _HAE_REGISTER {
+ UCHAR Reserved : 1;
+ UCHAR UpperEisaAdd : 7;
+} HAE_REGISTER, *PHAE_REGISTER;
+
+#define HAE ( (volatile PHAE_REGISTER) HAE_VIRTUAL_BASE )
+
+typedef struct _SYSCTL_REGISTER {
+ UCHAR Reserved : 2;
+ UCHAR MemConfig : 2;
+ UCHAR LED : 4;
+} SYSCTL_REGISTER, *PSYSCTL_REGISTER;
+
+#define SYSCTL ( (volatile PSYSCTL_REGISTER) SYSCTL_VIRTUAL_BASE )
+
+
+
+//
+// COM controller register pointer definitions.
+//
+#define SP1_READ ( (volatile PSP_READ_REGISTERS) COMPORT1_VIRTUAL_BASE )
+#define SP1_WRITE ( (volatile PSP_WRITE_REGISTERS)COMPORT1_VIRTUAL_BASE )
+
+#define SP2_READ ( (volatile PSP_READ_REGISTERS) COMPORT2_VIRTUAL_BASE )
+#define SP2_WRITE ( (volatile PSP_WRITE_REGISTERS)COMPORT2_VIRTUAL_BASE )
+
+
+
+//
+// PARALLEL port write registers.
+//
+
+typedef struct _PARALLEL_WRITE_REGISTERS {
+ UCHAR Data;
+ UCHAR Invalid;
+ UCHAR Control;
+ } PARALLEL_WRITE_REGISTERS, * PPARALLEL_WRITE_REGISTERS;
+
+//
+// PARALLEL port read Registers
+//
+
+typedef struct _PARALLEL_READ_REGISTERS {
+ UCHAR Data;
+ UCHAR Status;
+ UCHAR Control;
+ } PARALLEL_READ_REGISTERS,* PPARALLEL_READ_REGISTERS;
+
+//
+// PARALLEL controller register pointer definitions.
+//
+
+#define PARALLEL_READ ( (volatile PPARALLEL_READ_REGISTERS)PARALLEL_VIRTUAL_BASE )
+#define PARALLEL_WRITE ( (volatile PPARALLEL_WRITE_REGISTERS)PARALLEL_VIRTUAL_BASE )
+
+//
+// FLOPPY read registers.
+//
+
+typedef struct _FLOPPY_READ_REGISTERS {
+ UCHAR StatusA;
+ UCHAR StatusB;
+ UCHAR DigitalOutput;
+ UCHAR Reserved1;
+ UCHAR MainStatus;
+ UCHAR Fifo;
+ UCHAR Reserved2;
+ UCHAR DigitalInput;
+ } FLOPPY_READ_REGISTERS, * PFLOPPY_READ_REGISTERS;
+
+//
+// FLOPPY write registers.
+//
+
+typedef struct _FLOPPY_WRITE_REGISTERS {
+ UCHAR StatusA;
+ UCHAR StatusB;
+ UCHAR DigitalOutput;
+ UCHAR Reserved1;
+ UCHAR DataRateSelect;
+ UCHAR Fifo;
+ UCHAR Reserved2;
+ UCHAR ConfigurationControl;
+ } FLOPPY_WRITE_REGISTERS, * PFLOPPY_WRITE_REGISTERS ;
+
+//
+// FLOPPY controller register pointer definitions.
+//
+
+
+#define FLOPPY_READ ((volatile PFLOPPY_READ_REGISTERS)FLOPPY_VIRTUAL_BASE)
+#define FLOPPY_WRITE ((volatile PFLOPPY_WRITE_REGISTERS)FLOPPY_VIRTUAL_BASE)
+
+//
+// KEYBOARD write registers.
+//
+typedef struct _KEYBOARD_WRITE_REGISTERS {
+ UCHAR Data; // port 60H
+ UCHAR Filler[3];
+ UCHAR Command; // port 64H
+ } KEYBOARD_WRITE_REGISTERS, * PKEYBOARD_WRITE_REGISTERS;
+
+//
+// KEYBOARD read Registers
+//
+
+typedef struct _KEYBOARD_READ_REGISTERS {
+ UCHAR Data; // port 60H
+ UCHAR Filler[3];
+ UCHAR Status; // port 64H
+ } KEYBOARD_READ_REGISTERS, * PKEYBOARD_READ_REGISTERS;
+
+//
+// KEYBOARD controller register pointer definitions.
+//
+#define KEYBOARD_READ ( (volatile PKEYBOARD_READ_REGISTERS)KEYBOARD_VIRTUAL_BASE )
+#define KEYBOARD_WRITE ( (volatile PKEYBOARD_WRITE_REGISTERS)KEYBOARD_VIRTUAL_BASE)
+
+//
+// Keyboard circular buffer type definition.
+//
+#define KBD_BUFFER_SIZE 32
+
+typedef struct _KEYBOARD_BUFFER {
+ volatile UCHAR Buffer[KBD_BUFFER_SIZE];
+ volatile UCHAR ReadIndex;
+ volatile UCHAR WriteIndex;
+} KEYBOARD_BUFFER, *PKEYBOARD_BUFFER;
+
+
+#define TIME_OUT 0xdead
+
+//
+// EISA Stuff
+// ***** temp **** this should be replaced by the definition in
+// "ntos\inc\eisa.h" as soon as it is complete.
+//
+
+typedef struct _EISA {
+ UCHAR Dma1Ch0Address; //0x00
+ UCHAR Dma1Ch0Count; //0x01
+ UCHAR Dma1Ch1Address; //0x02
+ UCHAR Dma1Ch1Count; //0x03
+ UCHAR Dma1Ch2Address; //0x04
+ UCHAR Dma1Ch2Count; //0x05
+ UCHAR Dma1Ch3Address; //0x06
+ UCHAR Dma1Ch3Count; //0x07
+ UCHAR Dma1StatusCommand; //0x08
+ UCHAR Dma1Request; //0x09
+ UCHAR Dma1SingleMask; //0x0a
+ UCHAR Dma1Mode; //0x0b
+ UCHAR Dma1ClearBytePointer; //0x0c
+ UCHAR Dma1MasterClear; //0x0d
+ UCHAR Dma1ClearMask; //0x0e
+ UCHAR Dma1AllMask; //0x0f
+ ULONG Fill01; //0x10-13
+ ULONG Fill02; //0x14-17
+ ULONG Fill03; //0x18-1b
+ ULONG Fill04; //0x1c-1f
+ UCHAR Int1Control; //0x20
+ UCHAR Int1Mask; //0x21
+ USHORT Fill10; //0x22-23
+ ULONG Fill11; //0x24
+ ULONG Fill12; //0x28
+ ULONG Fill13; //0x2c
+ ULONG Fill14; //0x30
+ ULONG Fill15; //0x34
+ ULONG Fill16; //0x38
+ ULONG Fill17; //0x3c
+ UCHAR IntTimer1SystemClock; //0x40
+ UCHAR IntTimer1RefreshRequest; //0x41
+ UCHAR IntTimer1SpeakerTone; //0x42
+ UCHAR IntTimer1CommandMode; //0x43
+ ULONG Fill20; //0x44
+ UCHAR IntTimer2FailsafeClock; //0x48
+ UCHAR IntTimer2Reserved; //0x49
+ UCHAR IntTimer2CPUSpeeedCtrl; //0x4a
+ UCHAR IntTimer2CommandMode; //0x4b
+ ULONG Fill30; //0x4c
+ ULONG Fill31; //0x50
+ ULONG Fill32; //0x54
+ ULONG Fill33; //0x58
+ ULONG Fill34; //0x5c
+ UCHAR Fill35; //0x60
+ UCHAR NMIStatus; //0x61
+ UCHAR Fill40; //0x62
+ UCHAR Fill41; //0x63
+ ULONG Fill42; //0x64
+ ULONG Fill43; //0x68
+ ULONG Fill44; //0x6c
+ UCHAR NMIEnable; //0x70
+ }EISA, * PEISA;
+
+#define ISP ( (volatile PEISA) EISA_IO_VIRTUAL_BASE )
+
+#define EISA_CONTROL ( (volatile PEISA_CONTROL) EISA_IO_VIRTUAL_BASE )
+
+
+#endif // _IODEVICE_
diff --git a/private/ntos/fw/alpha/jenassem.s b/private/ntos/fw/alpha/jenassem.s
new file mode 100644
index 000000000..aaf4545a2
--- /dev/null
+++ b/private/ntos/fw/alpha/jenassem.s
@@ -0,0 +1,579 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+
+Module Name:
+
+ jenassem.s
+
+
+Abstract:
+
+ This contains assembler code routines for the Alpha PCs.
+
+ The first section contains functions that need to explicitly
+ generate Alpha macroinstructions (e.g., mb, PALcode calls).
+ These could be asm() calls within the C code, but our compiler does
+ not now handle asm()'s and may not for some time.
+
+ The second section has linkages for "Fw" calls.
+
+ The last section has stubs for functions that should be defined
+ elsewhere, but are not. When the real code appears in the
+ Alpha build tree, these stub routines should be deleted.
+
+ Most of the "Fw" call section is directly patterned after
+ \nt\private\ntos\fw\mips\fwtrap.s, written by Lluis Abello of
+ Microsoft.
+
+
+Author:
+
+ John DeRosa [DEC] 21-May-1992
+
+
+Environment:
+
+ Executes in kernel mode.
+
+Revision History:
+
+
+--*/
+
+
+#include "ksalpha.h"
+#include "selfmap.h"
+#include "machdef.h"
+
+//
+// Static data
+//
+
+.align 4
+RegisterTable:
+.space RegisterTableSize
+
+
+/*++
+
+VOID
+FwStallExecution (
+ IN ULONG MicroSeconds
+)
+
+
+Routine Description:
+
+ This stalls for at least the requested number of microseconds.
+ Current timing on a Jensen indicates that this is pessimistic
+ by a factor of 1.2.
+
+Arguments:
+
+ Microseconds (a0) - The number of microseconds to stall.
+
+
+Return Value:
+
+ None.
+
+--*/
+
+ LEAF_ENTRY( FwStallExecution)
+
+ beq a0, 20f // exit if zero delay requested
+
+// lda t0, 20000(zero) // force small delays to 20 milliseconds
+// subl a0, 5, t1
+// cmoveq t1, t0, a0
+
+10: bsr t3, 100f // call 1 microsecond delay subroutine
+
+ subl a0, 1, a0 // decrement requested microseconds
+ zap a0, 0xf0, a0 // unsigned long a0
+
+ bgt a0, 10b
+
+20: ret zero, (ra)
+
+//
+// 1 microsecond delay subroutine
+//
+
+100: ldl t0, CyclesPerMicrosecond // init 1 microsecond delay
+
+ rpcc t1 // get entry time rpcc value
+ zap t1, 0xf0, t1 // clear <63:32>
+
+200: rpcc t2 // get current rpcc value
+ zap t2, 0xf0, t2 // clear <63:32>
+
+ subl t2, t1, t2 // compute unsigned 32b difference
+ zap t2, 0xf0, t2
+
+ subl t0, t2, t2 // (requested delay - delay so far) > 0?
+
+ bgt t2, 200b
+
+ ret zero, (t3)
+
+ .end FwStallExecution
+
+
+
+/*****************************************************************
+
+Simple functions to perform PALcode calls and memory barriers.
+
+******************************************************************/
+
+
+ LEAF_ENTRY(AlphaInstIMB)
+
+ callpal imb
+ ret zero, (ra)
+
+ .end AlphaInstIMB
+
+
+
+ LEAF_ENTRY(AlphaInstMB)
+
+ mb
+ ret zero, (ra)
+
+ .end AlphaInstMB
+
+
+
+ LEAF_ENTRY(AlphaInstHalt)
+
+ callpal halt
+ ret zero, (ra) # should never return, but...
+
+ .end AlphaInstHalt
+
+
+
+ LEAF_ENTRY(DisableInterrupts)
+
+ callpal di
+ ret zero, (ra)
+
+ .end DisableInterrupts
+
+
+
+ LEAF_ENTRY(RegisterExceptionHandler)
+
+ lda a0, Monitor # Run monitor on unexpected exceptions
+ callpal wrentry
+ ret zero, (ra)
+
+ .end RegisterExceptionHandler
+
+ NESTED_ENTRY(FwExecute, 0x60, ra)
+
+
+/*++
+
+Routine Description:
+
+ This is the entry point for the Execute service.
+
+ It behaves in two different ways depending on where it is called from:
+
+ 1) If called from the Firmware, it saves the stack pointer
+ in a fixed location and then saves all the saved registers
+ in the stack. This is the stack that will be used to restore
+ the saved state when returning to the firmware.
+
+ 2) If called from a loaded program, the program to be loaded
+ and executed can overwrite the current program and its
+ stack. Therefore a temporary stack is set.
+
+Arguments:
+
+ a0 = IN PCHAR Path,
+ a1 = IN ULONG Argc,
+ a2 = IN PCHAR Argv[],
+ a3 = IN PCHAR Envp[]
+
+Return Value:
+
+ ARC_STATUS returned by FwPrivateExecute.
+ Always returns to the Firmware.
+
+--*/
+
+ //
+ // If the longword is zero then this is the first call from
+ // the firmware, and is not a call from an already loaded program.
+ //
+
+ lda t0, FwSavedSp
+ ldl t1, (t0)
+ beq t1, CallFromFw
+
+
+ //
+ // Here when an already loaded program wants to be replaced
+ // by another program. Therefore, the current stack and state
+ // will be trashed and a new temporary stack needs to be set.
+ // (A temporary stack is used to guarantee that there is enough
+ // stack space for the necessary calls.)
+ //
+
+ lda t0, FwTemporaryStack
+ ldl sp, (t0)
+ jsr ra, FwPrivateExecute # this does the dirty work.
+
+ //
+ // The executed program has returned. Its caller is gone.
+ // Therefore, restore the initial firmware stack and return
+ // to the firmware instead.
+ //
+
+ lda t0, FwSavedSp
+ ldl sp, (t0) # restore saved stack
+ br zero, RestoreFwState # go restore the state & return
+
+
+
+
+CallFromFw:
+
+ subq sp, 0x60 # make room in the stack
+ stl sp, (t0) # save new stack pointer
+
+ stq ra, (sp) # return address on top of stack
+ stq s0, 0x8(sp) # save s registers
+ stq s1, 0x10(sp)
+ stq s2, 0x18(sp)
+ stq s3, 0x20(sp)
+ stq s4, 0x28(sp)
+ stq s5, 0x30(sp)
+ stq fp, 0x38(sp)
+ stq gp, 0x40(sp)
+
+ jsr ra, FwPrivateExecute # go do the work.
+
+
+RestoreFwState:
+
+ ldq ra, (sp) # restore return address
+ ldq s0, 0x8(sp) # restore s registers
+ ldq s1, 0x10(sp)
+ ldq s2, 0x18(sp)
+ ldq s3, 0x20(sp)
+ ldq s4, 0x28(sp)
+ ldq s5, 0x30(sp)
+ ldq fp, 0x38(sp)
+ ldq gp, 0x40(sp)
+ addq sp, 0x60 # restore stack pointer
+
+ ret zero, (ra) # return to firmware control
+
+ .end FwExecute
+
+ NESTED_ENTRY(FwInvoke, 0x40, ra)
+
+/*++
+ARC_STATUS
+FwInvoke(
+ IN ULONG ExecAddr,
+ IN ULONG StackAddr,
+ IN ULONG Argc,
+ IN PCHAR Argv[],
+ IN PCHAR Envp[]
+ )
+
+
+Routine Description:
+
+ This routine invokes a loaded program.
+
+Arguments:
+
+ ExecAddr - Supplies the address of the routine to call.
+
+ StackAddr - Supplies the address to which the stack pointer is set.
+
+ Argc, Argv, Envp - Supply the arguments and environment to pass to
+ Loaded program.
+
+ The stack pointer is saved in register s0 so that when the loaded
+ program returns, the old stack pointer can be restored.
+
+
+Return Value:
+
+ ESUCCESS is returned if the address is valid.
+ EFAULT indicates an invalid address.
+
+--*/
+
+
+ subq sp, 0x40 # make room on the stack
+ stq ra, (sp) # save ra on top of stack
+ stq s0, 0x8(sp) # save s0
+ and a0, 3, t1 # return EFAULT if unaligned address
+ ldiq v0, 0x6
+ bne t1, 1f # branch if address alignment error
+
+ mov a0, t12 # save program address in t12
+
+ mov sp, s0 # save stack pointer
+ mov a1, sp # ..and load new one for program
+ mov a2, a0 # argc becomes first argument
+ mov a3, a1 # argv becomes second argument
+ mov a4, a2 # envp becomes third argument
+
+ jsr ra, (t12) # call program
+
+ //
+ // here if loaded program returns.
+ //
+
+ mov s0, sp # restore stack pointer
+ mov zero, v0 # return ESUCCESS value
+ ldq s0, 0x8(sp) # restore things
+ ldq ra, (sp)
+1:
+ addq sp, 0x40
+ ret zero, (ra)
+
+ .end FwInvoke
+
+ NESTED_ENTRY(FwMonitor, 50, ra)
+
+/*****************************************************************
+
+Linkage to the monitor from the jxboot.c boot menu and code in
+bldr\alpha\stubs.c.
+
+******************************************************************/
+
+
+ //
+ // Move registers into exception frame and call the Monitor.
+ // We cannot exactly duplicate what the PALcode creates
+ // on an exception.
+ //
+ // This used to specify the stq addresses as
+ // RegisterTable+offset(zero)
+ // but the assembler won't generate correct code that way.
+ //
+
+ subq sp, 0x8 # setup t0 with base of register table,
+ stq t0, (sp) # and use t1 to store old t0 in it.
+ lda t0, RegisterTable
+ stq t1, t1RegTable(t0)
+ ldq t1, (sp)
+ stq t1, t0RegTable(t0)
+ addq sp, 0x8
+
+ stq v0, v0RegTable(t0)
+/* stq t0, RegisterTable+t0RegTable(zero) */
+/* stq t1, RegisterTable+t1RegTable(zero) */
+ stq t2, t2RegTable(t0)
+ stq t3, t3RegTable(t0)
+ stq t4, t4RegTable(t0)
+ stq t5, t5RegTable(t0)
+ stq t6, t6RegTable(t0)
+ stq t7, t7RegTable(t0)
+ stq s0, s0RegTable(t0)
+ stq s1, s1RegTable(t0)
+ stq s2, s2RegTable(t0)
+ stq s3, s3RegTable(t0)
+ stq s4, s4RegTable(t0)
+ stq s5, s5RegTable(t0)
+ stq fp, fpRegTable(t0)
+ stq a0, a0RegTable(t0)
+ stq a1, a1RegTable(t0)
+ stq a2, a2RegTable(t0)
+ stq a3, a3RegTable(t0)
+ stq a4, a4RegTable(t0)
+ stq a5, a5RegTable(t0)
+ stq t8, t8RegTable(t0)
+ stq t9, t9RegTable(t0)
+ stq t10, t10RegTable(t0)
+ stq t11, t11RegTable(t0)
+ stq ra, raRegTable(t0)
+ stq t12, t12RegTable(t0)
+ .set noat
+ stq AT, atRegTable(t0)
+ .set at
+ stq gp, gpRegTable(t0)
+ stq sp, spRegTable(t0)
+ stq zero, zeroRegTable(t0)
+ stt f0, f0RegTable(t0)
+ stt f1, f1RegTable(t0)
+ stt f2, f2RegTable(t0)
+ stt f3, f3RegTable(t0)
+ stt f4, f4RegTable(t0)
+ stt f5, f5RegTable(t0)
+ stt f6, f6RegTable(t0)
+ stt f7, f7RegTable(t0)
+ stt f8, f8RegTable(t0)
+ stt f9, f9RegTable(t0)
+ stt f10, f10RegTable(t0)
+ stt f11, f11RegTable(t0)
+ stt f12, f12RegTable(t0)
+ stt f13, f13RegTable(t0)
+ stt f14, f14RegTable(t0)
+ stt f15, f15RegTable(t0)
+ stt f16, f16RegTable(t0)
+ stt f17, f17RegTable(t0)
+ stt f18, f18RegTable(t0)
+ stt f19, f19RegTable(t0)
+ stt f20, f20RegTable(t0)
+ stt f21, f21RegTable(t0)
+ stt f22, f22RegTable(t0)
+ stt f23, f23RegTable(t0)
+ stt f24, f24RegTable(t0)
+ stt f25, f25RegTable(t0)
+ stt f26, f26RegTable(t0)
+ stt f27, f27RegTable(t0)
+ stt f28, f28RegTable(t0)
+ stt f29, f29RegTable(t0)
+ stt f30, f30RegTable(t0)
+ stt f31, f31RegTable(t0)
+
+ ldil t1, 0xedbedbed # phony exception type
+ stl t1, ResExceptTypeRegTable(t0)
+
+ # a0 has the CallerSource argument
+ # already.
+ lda a1, RegisterTable # Frame argument
+ jsr ra, Monitor
+
+
+ //
+ // On return just restore ra from the RegisterTable.
+ // This is coded this way to get around an assembler bug...
+ //
+
+// ldq ra, RegisterTable+raRegTable
+ lda t0, RegisterTable
+ ldq ra, raRegTable(t0)
+ ret zero, (ra)
+
+ .end FwMonitor
+
+#if 0
+
+//
+// This function was used to zero out memory in the selftest.c module.
+// We do not need to do this anymore.
+//
+
+/****
+
+VOID
+WildZeroMemory(
+ IN ULONG StartAddress,
+ IN ULONG Size
+ )
+Routine Description:
+
+ This routine zeroes the specified range of memory.
+
+ At some point this may be changed to a more clever algorithm,
+ For now, it simply does store quads.
+
+Arguments:
+
+ a0 - supplies the base physical address of the range of memory
+ to zero. It must be a multiple of the data cache line
+ size.
+
+ a1 - supplies length of memory to zero, in bytes. This must
+ be a multiple of the data cache line size.
+
+
+Return Value:
+
+ None.
+
+--*/
+
+ LEAF_ENTRY(WildZeroMemory)
+
+ mov a0, t0 # start address
+ mov a1, t1 # number of bytes to move
+
+1:
+ subqv t1, 0x20 # zero a D-cache block = 32 bytes
+ stq zero, (t0)
+ stq zero, 0x8(t0)
+ stq zero, 0x10(t0)
+ stq zero, 0x18(t0)
+ addqv t0, 0x20 # move to next cache block
+ bgt t1, 1b # t1 = 0 when done.
+
+ ret zero, (ra)
+
+ .end WildZeroMemory
+
+#endif
+
+
+#ifdef ALPHA_FW_KDHOOKS
+
+/*++
+
+VOID
+FwRfe(
+ VOID
+ )
+
+Routine Description:
+
+ This routine executes a return from exception instruction.
+ It is used to return after processing a breakpoint.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+ LEAF_ENTRY(FwRfe)
+
+ bis a0, zero, sp # Set the stack pointer to the
+ # exception frame pointer.
+ lda sp, -0x10(sp) # Adjust for stack empty space
+ callpal rfe # This does NOT return.
+
+ .end FwRfe
+
+#endif
+
+
+/************************************************************
+
+Stubs.
+
+*************************************************************/
+
+#ifndef ALPHA_FW_KDHOOKS
+
+//
+// This cannot be defined for kd build.
+//
+
+ LEAF_ENTRY(DebugPrompt)
+
+ callpal halt # surprise!
+ ret zero, (ra) # should never return, but...
+
+ .end DebugPrompt
+
+#endif
diff --git a/private/ntos/fw/alpha/jenfonts.c b/private/ntos/fw/alpha/jenfonts.c
new file mode 100644
index 000000000..d650c5720
--- /dev/null
+++ b/private/ntos/fw/alpha/jenfonts.c
@@ -0,0 +1,961 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+
+Module Name:
+
+ jenfonts.c
+
+Abstract:
+
+ 8x16 pixel fonts for the VGA video boot driver. The normal printing
+ ASCII characters were stolen from David Conroy's Beta-machine fonts.
+
+Author:
+
+ John DeRosa 7-May-1992
+
+Revision History:
+
+--*/
+
+#include "fwp.h"
+
+// Undefined characters.
+UCHAR VGA8x16Undef[] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+ };
+
+
+//
+// Normal ASCII characters 0x20 -- 0x7f (space -- del). Each byte is one
+// scan line, and each character is 2 rows.
+//
+// The bullet character is in the del slot.
+//
+UCHAR VGA8x16Chars[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ASCII 0x20, space
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, // ASCII 0x21, !
+ 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, // ASCII 0x22, "
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0xFF, 0xFF, 0x66, 0x66, // ASCII 0x23, #
+ 0xFF, 0xFF, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+ 0x18, 0x18, 0x3E, 0x7E, 0x60, 0x60, 0x7C, 0x3E, // ASCII 0x24, $
+ 0x06, 0x06, 0x7E, 0x7C, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0x6C, 0x0C, 0x18, 0x18, // ASCII 0x25, %
+ 0x30, 0x36, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+ 0x38, 0x7C, 0x6C, 0x6C, 0x38, 0x38, 0x70, 0x70, // ASCII 0x26, &
+ 0xDE, 0xDE, 0xCC, 0xCC, 0xFE, 0x76, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, // ASCII 0x27, '
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x0C, 0x1C, 0x18, 0x18, 0x18, // ASCII 0x28, (
+ 0x18, 0x18, 0x18, 0x1C, 0x0C, 0x06, 0x00, 0x00,
+ 0x00, 0x00, 0x60, 0x30, 0x38, 0x18, 0x18, 0x18, // ASCII 0x29, )
+ 0x18, 0x18, 0x18, 0x38, 0x30, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0x3C, 0x3C, 0xFF, 0xFF, // ASCII 0x2a, *
+ 0x3C, 0x3C, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x7E, 0x7E, // ASCII 0x2b, +
+ 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ASCII 0x2c, ,
+ 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x30, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, // ASCII 0x2d, -
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ASCII 0x2e, .
+ 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x06, 0x06, 0x0C, 0x0C, 0x18, // ASCII 0x2f, /
+ 0x18, 0x30, 0x30, 0x60, 0x60, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x3C, 0x7E, 0x66, 0x66, 0x66, 0x6E, // ASCII 0x30, 0
+ 0x76, 0x66, 0x66, 0x66, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x18, 0x38, 0x38, 0x18, 0x18, // ASCII 0x31, 1
+ 0x18, 0x18, 0x18, 0x18, 0x7E, 0x7E, 0x00, 0x00,
+ 0x00, 0x00, 0x3C, 0x7E, 0x66, 0x66, 0x0C, 0x0C, // ASCII 0x32, 2
+ 0x18, 0x18, 0x30, 0x30, 0x7E, 0x7E, 0x00, 0x00,
+ 0x00, 0x00, 0x7E, 0x7E, 0x0C, 0x0C, 0x18, 0x18, // ASCII 0x33, 3
+ 0x0C, 0x0C, 0x66, 0x66, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x0C, 0x0C, 0x1C, 0x1C, 0x3C, 0x3C, // ASCII 0x34, 4
+ 0x6C, 0x6C, 0x7E, 0x7E, 0x0C, 0x0C, 0x00, 0x00,
+ 0x00, 0x00, 0x7E, 0x7E, 0x60, 0x60, 0x7C, 0x7E, // ASCII 0x35, 5
+ 0x06, 0x06, 0x06, 0x66, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x1C, 0x3C, 0x70, 0x60, 0x60, 0x7C, // ASCII 0x36, 6
+ 0x7E, 0x66, 0x66, 0x66, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x7E, 0x7E, 0x06, 0x06, 0x0C, 0x0C, // ASCII 0x37, 7
+ 0x18, 0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x3C, 0x7E, 0x66, 0x66, 0x3C, 0x3C, // ASCII 0x38, 8
+ 0x66, 0x66, 0x66, 0x66, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x3C, 0x7E, 0x66, 0x66, 0x7E, 0x3E, // ASCII 0x39, 9
+ 0x06, 0x06, 0x06, 0x0E, 0x3C, 0x38, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, // ASCII 0x3a, :
+ 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, // ASCII 0x3b, ;
+ 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x30, 0x20,
+ 0x00, 0x00, 0x00, 0x0E, 0x1C, 0x38, 0x70, 0xE0, // ASCII 0x3c, <
+ 0x70, 0x38, 0x1C, 0x0E, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0x00, 0x00, // ASCII 0x3d, =
+ 0x7E, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xE0, 0x70, 0x38, 0x1C, 0x0E, // ASCII 0x3e, >
+ 0x1C, 0x38, 0x70, 0xE0, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x3C, 0x7E, 0x66, 0x66, 0x0C, 0x0C, // ASCII 0x3f, ?
+ 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x38, 0x7C, 0xE6, 0xC2, 0xDA, 0xD6, // ASCII 0x40, @
+ 0xD6, 0xDC, 0xC0, 0xE2, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x3C, 0x7E, 0x66, 0x66, 0x66, // ASCII 0x41, A
+ 0x7E, 0x7E, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00,
+ 0x00, 0x00, 0x7C, 0x7E, 0x66, 0x66, 0x7E, 0x7C, // ASCII 0x42, B
+ 0x66, 0x66, 0x66, 0x66, 0x7E, 0x7C, 0x00, 0x00,
+ 0x00, 0x00, 0x3C, 0x7E, 0x66, 0x66, 0x60, 0x60, // ASCII 0x43, C
+ 0x60, 0x60, 0x66, 0x66, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x78, 0x7C, 0x6E, 0x66, 0x66, 0x66, // ASCII 0x44, D
+ 0x66, 0x66, 0x66, 0x6E, 0x7C, 0x78, 0x00, 0x00,
+ 0x00, 0x00, 0x7E, 0x7E, 0x60, 0x60, 0x7C, 0x7C, // ASCII 0x45, E
+ 0x60, 0x60, 0x60, 0x60, 0x7E, 0x7E, 0x00, 0x00,
+ 0x00, 0x00, 0x7E, 0x7E, 0x60, 0x60, 0x7C, 0x7C, // ASCII 0x46, F
+ 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x3E, 0x7E, 0x60, 0x60, 0x6E, 0x6E, // ASCII 0x47, G
+ 0x66, 0x66, 0x66, 0x66, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x7E, 0x7E, // ASCII 0x48, H
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00,
+ 0x00, 0x00, 0x7E, 0x7E, 0x18, 0x18, 0x18, 0x18, // ASCII 0x49, I
+ 0x18, 0x18, 0x18, 0x18, 0x7E, 0x7E, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, // ASCII 0x4a, J
+ 0x06, 0x06, 0x66, 0x66, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0xCC, 0xCC, 0xD8, 0xD8, 0xF0, 0xF0, // ASCII 0x4b, K
+ 0xD8, 0xD8, 0xCC, 0xCC, 0xC6, 0xC6, 0x00, 0x00,
+ 0x00, 0x00, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, // ASCII 0x4c, L
+ 0x60, 0x60, 0x60, 0x60, 0x7E, 0x7E, 0x00, 0x00,
+ 0x00, 0x00, 0xC6, 0xC6, 0xEE, 0xEE, 0xFE, 0xD6, // ASCII 0x4d, M
+ 0xD6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0x66, 0x76, 0x76, 0x7E, // ASCII 0x4e, N
+ 0x7E, 0x6E, 0x6E, 0x66, 0x66, 0x66, 0x00, 0x00,
+ 0x00, 0x00, 0x3C, 0x7E, 0x66, 0x66, 0x66, 0x66, // ASCII 0x4f, O
+ 0x66, 0x66, 0x66, 0x66, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x7C, 0x7E, 0x66, 0x66, 0x66, 0x66, // ASCII 0x50, P
+ 0x7E, 0x7C, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x3C, 0x7E, 0x66, 0x66, 0x66, 0x66, // ASCII 0x51, Q
+ 0x66, 0x66, 0x66, 0x6A, 0x7C, 0x36, 0x00, 0x00,
+ 0x00, 0x00, 0xF8, 0xFC, 0xCC, 0xCC, 0xCC, 0xFC, // ASCII 0x52, R
+ 0xF8, 0xD8, 0xCC, 0xCC, 0xC6, 0xC6, 0x00, 0x00,
+ 0x00, 0x00, 0x3E, 0x7E, 0x60, 0x60, 0x70, 0x38, // ASCII 0x53, S
+ 0x1C, 0x0E, 0x06, 0x06, 0x7E, 0x7C, 0x00, 0x00,
+ 0x00, 0x00, 0x7E, 0x7E, 0x18, 0x18, 0x18, 0x18, // ASCII 0x54, T
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, // ASCII 0x55, U
+ 0x66, 0x66, 0x66, 0x66, 0x7E, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, // ASCII 0x56, V
+ 0x66, 0x66, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xD6, // ASCII 0x57, W
+ 0xD6, 0xFE, 0xFE, 0xEE, 0xC6, 0x82, 0x00, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0x66, 0x3C, 0x3C, 0x18, // ASCII 0x58, X
+ 0x18, 0x3C, 0x3C, 0x66, 0x66, 0x66, 0x00, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x3C, // ASCII 0x59, Y
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x7E, 0x7E, 0x0C, 0x0C, 0x18, 0x18, // ASCII 0x5a, Z
+ 0x30, 0x30, 0x60, 0x60, 0x7E, 0x7E, 0x00, 0x00,
+ 0x00, 0x00, 0x1E, 0x1E, 0x18, 0x18, 0x18, 0x18, // ASCII 0x5b, [
+ 0x18, 0x18, 0x18, 0x18, 0x1E, 0x1E, 0x00, 0x00,
+ 0x00, 0x00, 0x60, 0x60, 0x60, 0x30, 0x30, 0x18, // ASCII 0x5c, \
+ 0x18, 0x0C, 0x0C, 0x06, 0x06, 0x06, 0x00, 0x00,
+ 0x00, 0x00, 0x78, 0x78, 0x18, 0x18, 0x18, 0x18, // ASCII 0x5d, ]
+ 0x18, 0x18, 0x18, 0x18, 0x78, 0x78, 0x00, 0x00,
+ 0x00, 0x10, 0x10, 0x38, 0x38, 0x6C, 0x6C, 0xC6, // ASCII 0x5e, ^
+ 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ASCII 0x5f, _
+ 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00,
+ 0x40, 0x60, 0x70, 0x38, 0x1C, 0x0C, 0x04, 0x00, // ASCII 0x60, `
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x3E, 0x06, // ASCII 0x61, a
+ 0x3E, 0x7E, 0x66, 0x66, 0x7E, 0x3E, 0x00, 0x00,
+ 0x00, 0x00, 0x60, 0x60, 0x60, 0x7C, 0x7E, 0x66, // ASCII 0x62, b
+ 0x66, 0x66, 0x66, 0x66, 0x7E, 0x7C, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x7E, 0x60, // ASCII 0x63, c
+ 0x60, 0x60, 0x60, 0x60, 0x7E, 0x3E, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x06, 0x06, 0x3E, 0x7E, 0x66, // ASCII 0x64, d
+ 0x66, 0x66, 0x66, 0x66, 0x7E, 0x3E, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x7E, 0x66, // ASCII 0x65, e
+ 0x66, 0x7E, 0x60, 0x60, 0x7E, 0x3E, 0x00, 0x00,
+ 0x00, 0x00, 0x0E, 0x1E, 0x18, 0x18, 0x7E, 0x7E, // ASCII 0x66, f
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x7E, 0x66, // ASCII 0x67, g
+ 0x66, 0x66, 0x66, 0x7E, 0x3E, 0x06, 0x7E, 0x7C,
+ 0x00, 0x00, 0x60, 0x60, 0x60, 0x7C, 0x7E, 0x66, // ASCII 0x68, h
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x38, 0x18, // ASCII 0x69, i
+ 0x18, 0x18, 0x18, 0x18, 0x3C, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x0C, 0x0C, 0x00, 0x0C, 0x0C, 0x0C, // ASCII 0x6a, j
+ 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x7C, 0x78,
+ 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xCC, 0xDC, 0xF8, // ASCII 0x6b, k
+ 0xF0, 0xF8, 0xD8, 0xCC, 0xCE, 0xC6, 0x00, 0x00,
+ 0x00, 0x00, 0x38, 0x38, 0x18, 0x18, 0x18, 0x18, // ASCII 0x6c, l
+ 0x18, 0x18, 0x18, 0x18, 0x3C, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x6C, 0xFE, 0xFE, // ASCII 0x6d, m
+ 0xD6, 0xD6, 0xD6, 0xC6, 0xC6, 0xC6, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x7E, 0x66, // ASCII 0x6e, n
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x7E, 0x66, // ASCII 0x6f, o
+ 0x66, 0x66, 0x66, 0x66, 0x7e, 0x3c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x7e, 0x66, // ascii 0x70, p
+ 0x66, 0x66, 0x66, 0x66, 0x7e, 0x7c, 0x60, 0x60,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x7e, 0x66, // ascii 0x71, q
+ 0x66, 0x66, 0x66, 0x66, 0x7e, 0x3e, 0x06, 0x06,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x7e, 0x66, // ascii 0x72, r
+ 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x7e, 0x60, // ascii 0x73, s
+ 0x70, 0x3c, 0x0e, 0x06, 0x7e, 0x7c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x7e, 0x18, // ascii 0x74, t
+ 0x18, 0x18, 0x18, 0x18, 0x1e, 0x0e, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, // ascii 0x75, u
+ 0x66, 0x66, 0x66, 0x66, 0x7e, 0x3e, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, // ascii 0x76, v
+ 0x66, 0x66, 0x3c, 0x3c, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xd6, // ascii 0x77, w
+ 0xd6, 0xfe, 0xfe, 0xee, 0xc6, 0x82, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x3c, // ascii 0x78, x
+ 0x3c, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, // ascii 0x79, y
+ 0x66, 0x66, 0x66, 0x7e, 0x3e, 0x06, 0x7e, 0x7c,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x0c, // ascii 0x7a, z
+ 0x18, 0x18, 0x30, 0x30, 0x7e, 0x7e, 0x00, 0x00,
+ 0x00, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x38, 0xf0, // ascii 0x7b, {
+ 0xf0, 0x38, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00,
+ 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, // ascii 0x7c, |
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00,
+ 0x00, 0xe0, 0x30, 0x30, 0x30, 0x30, 0x38, 0x1e, // ascii 0x7d, }
+ 0x1e, 0x38, 0x30, 0x30, 0x30, 0x30, 0xe0, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0xf2, 0xbe, // ascii 0x7e, ~
+ 0x9c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, // ascii 0x7f, <bullet>
+ 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+#ifndef FAILSAFE_BOOTER
+//
+// Line drawing 8x16 characters. These sit in the character codes
+// 0xb3 -- 0xda.
+//
+UCHAR VGA8x16LineDrawing[] = {
+
+ // ASCII 0xb3
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+
+ // ASCII 0xb4
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0xf0, // 11110000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+
+ // ASCII 0xb5
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0xf0, // 11110000
+ 0x10, // 00010000
+ 0xf0, // 11110000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+
+ // ASCII 0xb6
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0xe8, // 11101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+
+ // ASCII 0xb7
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0xf8, // 11111000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+
+ // ASCII 0xb8
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0xf0, // 11110000
+ 0x10, // 00010000
+ 0xf0, // 11110000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+
+ // ASCII 0xb9
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0xe8, // 11101000
+ 0x08, // 00001000
+ 0xe8, // 11101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+
+ // ASCII 0xba
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+
+ // ASCII 0xbb
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0xf8, // 11111000
+ 0x08, // 00001000
+ 0xe8, // 11101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+
+ // ASCII 0xbc
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0xe8, // 11101000
+ 0x08, // 00001000
+ 0xf8, // 11111000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+
+ // ASCII 0xbd
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0xf8, // 11111000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+
+ // ASCII 0xbe
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0xf0, // 11110000
+ 0x10, // 00010000
+ 0xf0, // 11110000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+
+ // ASCII 0xbf
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0xf0, // 11110000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+
+ // ASCII 0xc0
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x1f, // 00011111
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+
+ // ASCII 0xc1
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0xff, // 11111111
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+
+ // ASCII 0xc2
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0xff, // 11111111
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+
+ // ASCII 0xc3
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x1f, // 00011111
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+
+ // ASCII 0xc4
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0xff, // 11111111
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+
+ // ASCII 0xc5
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0xff, // 11111111
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+
+ // ASCII 0xc6
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x1f, // 00011111
+ 0x10, // 00010000
+ 0x1f, // 00011111
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+
+ // ASCII 0xc7
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x2f, // 00101111
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+
+ // ASCII 0xc8
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x2f, // 00101111
+ 0x20, // 00100000
+ 0x3f, // 00111111
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+
+ // ASCII 0xc9
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x3f, // 00111111
+ 0x20, // 00100000
+ 0x2f, // 00101111
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+
+ // ASCII 0xca
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0xef, // 11101111
+ 0x00, // 00000000
+ 0xff, // 11111111
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+
+ // ASCII 0xcb
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0xff, // 11111111
+ 0x00, // 00000000
+ 0xef, // 11101111
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+
+ // ASCII 0xcc
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x2f, // 00101111
+ 0x20, // 00100000
+ 0x2f, // 00101111
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+
+ // ASCII 0xcd
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0xff, // 11111111
+ 0x00, // 00000000
+ 0xff, // 11111111
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+
+ // ASCII 0xce
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0xef, // 11101111
+ 0x00, // 00000000
+ 0xef, // 11101111
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+
+ // ASCII 0xcf
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0xff, // 11111111
+ 0x00, // 00000000
+ 0xff, // 11111111
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+
+ // ASCII 0xd0
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0xff, // 11111111
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+
+ // ASCII 0xd1
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0xff, // 11111111
+ 0x00, // 00000000
+ 0xff, // 11111111
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+
+ // ASCII 0xd2
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0xff, // 11111111
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+
+ // ASCII 0xd3
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x3f, // 00111111
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+
+ // ASCII 0xd4
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x1f, // 00011111
+ 0x10, // 00010000
+ 0x1f, // 00011111
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+
+ // ASCII 0xd5
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x1f, // 00011111
+ 0x10, // 00010000
+ 0x1f, // 00011111
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+
+ // ASCII 0xd6
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x3f, // 00111111
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+
+ // ASCII 0xd7
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0xff, // 11111111
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+ 0x28, // 00101000
+
+ // ASCII 0xd8
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0xff, // 11111111
+ 0x10, // 00010000
+ 0xff, // 11111111
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+
+ // ASCII 0xd9
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0xf0, // 11110000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+
+ // ASCII 0xda
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x00, // 00000000
+ 0x1f, // 00011111
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10, // 00010000
+ 0x10 // 00010000
+};
+
+#endif // ndef FAILSAFE_BOOTER
diff --git a/private/ntos/fw/alpha/jensen/alpha/aha174x.c b/private/ntos/fw/alpha/jensen/alpha/aha174x.c
new file mode 100644
index 000000000..0aaae6b1c
--- /dev/null
+++ b/private/ntos/fw/alpha/jensen/alpha/aha174x.c
@@ -0,0 +1,2035 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ aha174x.c
+
+Abstract:
+
+ This is the port driver for the AHA174X SCSI adapter.
+
+Authors:
+
+ Mike Glass
+
+Environment:
+
+ kernel mode only
+
+Notes:
+
+Revision History:
+
+--*/
+
+#include "miniport.h"
+#include "aha174x.h" // includes scsi.h
+
+//
+// Device extension
+//
+
+typedef struct _HW_DEVICE_EXTENSION {
+
+ PEISA_CONTROLLER EisaController;
+
+ UCHAR HostTargetId;
+
+ PSCSI_REQUEST_BLOCK PendingSrb;
+
+ UCHAR RequestCount[8][8];
+
+} HW_DEVICE_EXTENSION, *PHW_DEVICE_EXTENSION;
+
+//
+// Define the maximum number of outstanding I/O requests per logical unit.
+//
+
+#define MAX_QUEUE_DEPTH 2
+
+
+//
+// Function declarations
+//
+// Functions that start with 'Aha174x' are entry points
+// for the OS port driver.
+//
+
+ULONG
+DriverEntry(
+ IN PVOID DriverObject,
+ IN PVOID Argument2
+ );
+
+ULONG
+Aha174xEntry(
+ IN PVOID DriverObject,
+ IN PVOID Argument2
+ );
+
+ULONG
+Aha174xConfiguration(
+ IN PVOID DeviceExtension,
+ IN PVOID Context,
+ IN PVOID BusInformation,
+ IN PCHAR ArgumentString,
+ IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
+ OUT PBOOLEAN Again
+ );
+
+BOOLEAN
+Aha174xInitialize(
+ IN PVOID DeviceExtension
+ );
+
+BOOLEAN
+Aha174xStartIo(
+ IN PVOID DeviceExtension,
+ IN PSCSI_REQUEST_BLOCK Srb
+ );
+
+BOOLEAN
+Aha174xInterrupt(
+ IN PVOID DeviceExtension
+ );
+
+BOOLEAN
+Aha174xResetBus(
+ IN PVOID HwDeviceExtension,
+ IN ULONG PathId
+ );
+
+//
+// This function is called from Aha174xStartIo.
+//
+
+VOID
+A174xBuildEcb(
+ IN PHW_DEVICE_EXTENSION DeviceExtension,
+ IN PSCSI_REQUEST_BLOCK Srb
+ );
+
+//
+// This function is called from A174xBuildEcb.
+//
+
+VOID
+A174xBuildSgl(
+ IN PHW_DEVICE_EXTENSION DeviceExtension,
+ IN PSCSI_REQUEST_BLOCK Srb
+ );
+
+VOID
+A174xBuildRequestSense(
+ IN PVOID HwDeviceExtension,
+ IN PSCSI_REQUEST_BLOCK Srb
+ );
+
+BOOLEAN
+A174xSendCommand(
+ IN PHW_DEVICE_EXTENSION DeviceExtension,
+ IN UCHAR OperationCode,
+ IN ULONG Address
+ );
+
+//
+// This function is called from Aha174xInterrupt.
+//
+
+VOID
+A174xMapStatus(
+ IN PHW_DEVICE_EXTENSION DeviceExtension,
+ IN PSCSI_REQUEST_BLOCK Srb,
+ IN PSTATUS_BLOCK StatusBlock
+ );
+
+
+ULONG
+DriverEntry (
+ IN PVOID DriverObject,
+ IN PVOID Argument2
+ )
+
+/*++
+
+Routine Description:
+
+ Installable driver initialization entry point for system.
+
+Arguments:
+
+ Driver Object
+
+Return Value:
+
+ Status from ScsiPortInitialize()
+
+--*/
+
+{
+ return Aha174xEntry(DriverObject, Argument2);
+
+} // end DriverEntry()
+
+
+ULONG
+Aha174xEntry(
+ IN PVOID DriverObject,
+ IN PVOID Argument2
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called from DriverEntry if this driver is installable
+ or directly from the system if the driver is built into the kernel.
+ It scans the EISA slots looking for an AHA174X that is configured
+ to the ENHANCED mode.
+
+Arguments:
+
+ Driver Object
+
+Return Value:
+
+ Status from ScsiPortInitialize()
+
+--*/
+
+{
+ HW_INITIALIZATION_DATA hwInitializationData;
+ ULONG i;
+ ULONG AdapterCount = 0;
+
+ DebugPrint((1,"\n\nSCSI Aha174x MiniPort Driver\n"));
+
+ //
+ // Zero out structure.
+ //
+
+ for (i=0; i<sizeof(HW_INITIALIZATION_DATA); i++) {
+ ((PUCHAR)&hwInitializationData)[i] = 0;
+ }
+
+ //
+ // Set size of hwInitializationData.
+ //
+
+ hwInitializationData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA);
+
+ //
+ // Set entry points.
+ //
+
+ hwInitializationData.HwInitialize = Aha174xInitialize;
+ hwInitializationData.HwFindAdapter = Aha174xConfiguration;
+ hwInitializationData.HwStartIo = Aha174xStartIo;
+ hwInitializationData.HwInterrupt = Aha174xInterrupt;
+ hwInitializationData.HwResetBus = Aha174xResetBus;
+
+ //
+ // Set number of access ranges and bus type.
+ //
+
+ hwInitializationData.NumberOfAccessRanges = 2;
+ hwInitializationData.AdapterInterfaceType = Eisa;
+
+ //
+ // Indicate no buffer mapping but will need physical addresses.
+ //
+
+ hwInitializationData.NeedPhysicalAddresses = TRUE;
+
+ //
+ // Indicate auto request sense is supported.
+ //
+
+ hwInitializationData.MultipleRequestPerLu = TRUE;
+ hwInitializationData.AutoRequestSense = TRUE;
+
+ //
+ // Specify size of extensions.
+ //
+
+ hwInitializationData.DeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION);
+
+ //
+ // Ask for SRB extensions for ECBs.
+ //
+
+ hwInitializationData.SrbExtensionSize = sizeof(ECB);
+
+ return ScsiPortInitialize(DriverObject, Argument2, &hwInitializationData, &AdapterCount);
+
+} // end Aha174xEntry()
+
+
+ULONG
+Aha174xConfiguration(
+ IN PVOID HwDeviceExtension,
+ IN PVOID Context,
+ IN PVOID BusInformation,
+ IN PCHAR ArgumentString,
+ IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
+ OUT PBOOLEAN Again
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called by the OS-specific port driver after
+ the necessary storage has been allocated, to gather information
+ about the adapter's configuration.
+
+Arguments:
+
+ HwDeviceExtension - HBA miniport driver's adapter data storage
+ ConfigInfo - Configuration information structure describing HBA
+
+Return Value:
+
+ TRUE if adapter present in system
+
+--*/
+
+{
+ PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
+ PEISA_CONTROLLER eisaController;
+ ULONG eisaSlotNumber;
+ PVOID eisaAddress;
+ UCHAR dataByte;
+ PULONG adapterCount = Context;
+
+ //
+ // Check to see if adapter present in system.
+ //
+
+ for (eisaSlotNumber=*adapterCount + 1; eisaSlotNumber<MAXIMUM_EISA_SLOTS; eisaSlotNumber++) {
+
+ //
+ // Update the adapter count to indicate this slot has been checked.
+ //
+
+ (*adapterCount)++;
+
+ //
+ // Get the system address for this card.
+ // The card uses I/O space.
+ //
+
+ eisaAddress = ScsiPortGetDeviceBase(deviceExtension,
+ ConfigInfo->AdapterInterfaceType,
+ ConfigInfo->SystemIoBusNumber,
+ ScsiPortConvertUlongToPhysicalAddress(0x1000 * eisaSlotNumber),
+ 0x1000,
+ TRUE);
+
+ eisaController =
+ (PEISA_CONTROLLER)((PUCHAR)eisaAddress + EISA_ADDRESS_BASE);
+
+ if ((ScsiPortReadPortUchar(&eisaController->BoardId[0]) == 0x04) &&
+ (ScsiPortReadPortUchar(&eisaController->BoardId[1]) == 0x90) &&
+ (ScsiPortReadPortUchar(&eisaController->BoardId[2]) == 0x00)) {
+
+ DebugPrint((1,"AHA174X: Adapter found at EISA slot %d\n",
+ eisaSlotNumber));
+#ifdef MIPS
+ //
+ // Add code to configure the device if necessary. This is only
+ // needed until we get an EISA configuration program.
+ //
+
+ if (!(ScsiPortReadPortUchar(&eisaController->EBControl) & 0x1)) {
+
+ //
+ // The card as not been configured. Jam in a default one.
+ // Enable the card, enable enhanced mode operation, set the
+ // irql to 14, set the target id to 7 and enable the DMA.
+ //
+
+ ScsiPortWritePortUchar(&eisaController->EBControl, 1);
+ ScsiPortWritePortUchar(&eisaController->PortAddress, 0x80);
+ ScsiPortWritePortUchar(&eisaController->BiosAddress, 0x00);
+ ScsiPortWritePortUchar(&eisaController->Interrupt, 0x1d);
+ ScsiPortWritePortUchar(&eisaController->ScsiId, 0x7);
+ ScsiPortWritePortUchar(&eisaController->DmaChannel, 0x2);
+ ScsiPortStallExecution(1000);
+
+ }
+#endif
+
+#ifdef _ALPHA_
+
+ //
+ // This section is the only difference between this file and
+ // miniport\aha174x\aha174x.c. The firmware must do a
+ // hard initialization of the board, because it cannot
+ // rely on the EISA configuration information being present
+ // in the ROM.
+ //
+
+ //
+ // Configure the board for an Alpha AXP/Jensen machine.
+ //
+
+ //
+ // The card as not been configured. Jam in a default one.
+ // Enable the card, enable enhanced mode operation, set the
+ // irql to 14, set the target id to 7 and enable the DMA.
+ //
+
+ ScsiPortWritePortUchar(&eisaController->EBControl, 1);
+ ScsiPortWritePortUchar(&eisaController->PortAddress, 0x80);
+ ScsiPortWritePortUchar(&eisaController->BiosAddress, 0x00);
+ ScsiPortWritePortUchar(&eisaController->Interrupt, 0x1d);
+ ScsiPortWritePortUchar(&eisaController->ScsiId, 0x7);
+ ScsiPortWritePortUchar(&eisaController->DmaChannel, 0x2);
+ ScsiPortWritePortUchar(&eisaController->Control, CLEAR_INTERRUPT);
+
+#endif
+
+ if (ScsiPortReadPortUchar(&eisaController->PortAddress) &
+ ENHANCED_INTERFACE_ENABLED) {
+
+ //
+ // An adapter with the enhanced interface enabled was found.
+ //
+
+ break;
+
+ } else {
+
+ DebugPrint((1,"AHA174X: Adapter is in STANDARD mode\n"));
+ }
+ }
+
+ //
+ // If an adapter was not found unmap it.
+ //
+
+ ScsiPortFreeDeviceBase(deviceExtension,
+ eisaAddress);
+
+ } // end for (eisaSlotNumber ...
+
+ if (!(eisaSlotNumber < MAXIMUM_EISA_SLOTS)) {
+
+ //
+ // No adapter was found. Indicate that we are done and there are no
+ // more adapters here. Clear the adapter count for the next bus.
+ //
+
+ *Again = FALSE;
+ *adapterCount = 0;
+ return SP_RETURN_NOT_FOUND;
+ }
+
+ //
+ // There is still more to look at.
+ //
+
+ *Again = TRUE;
+
+ //
+ // Store base address of EISA registers in device extension.
+ //
+
+ deviceExtension->EisaController = eisaController;
+
+ ConfigInfo->InitiatorBusId[0] =
+ ScsiPortReadPortUchar(&eisaController->ScsiId) & 0x0F;
+
+ deviceExtension->HostTargetId = ConfigInfo->InitiatorBusId[0];
+
+ //
+ // Indicate maximum transfer length in bytes.
+ //
+
+ ConfigInfo->MaximumTransferLength = MAXIMUM_TRANSFER_SIZE;
+
+ //
+ // Maximum number of physical segments is 32.
+ //
+
+ ConfigInfo->NumberOfPhysicalBreaks = MAXIMUM_SGL_DESCRIPTORS;
+
+ ConfigInfo->ScatterGather = TRUE;
+ ConfigInfo->Master = TRUE;
+ ConfigInfo->NumberOfBuses = 1;
+
+ //
+ // Get the system interrupt vector and IRQL.
+ //
+
+ dataByte = ScsiPortReadPortUchar(&eisaController->Interrupt);
+ ConfigInfo->BusInterruptLevel = (dataByte & 7) + 9;
+
+ //
+ // Determine level or edge interrupt.
+ //
+
+ ConfigInfo->InterruptMode = dataByte & 0x08 ? Latched : LevelSensitive;
+
+ //
+ // Fill in the access array information.
+ //
+
+ (*ConfigInfo->AccessRanges)[0].RangeStart =
+ ScsiPortConvertUlongToPhysicalAddress(0x1000 * eisaSlotNumber + EISA_ADDRESS_BASE);
+ (*ConfigInfo->AccessRanges)[0].RangeLength = sizeof(EISA_CONTROLLER);
+ (*ConfigInfo->AccessRanges)[0].RangeInMemory = FALSE;
+
+
+ //
+ // Determine the BIOS address.
+ //
+
+ dataByte = ScsiPortReadPortUchar(&eisaController->BiosAddress);
+
+ if (dataByte & BIOS_ENABLED) {
+
+ dataByte &= BIOS_ADDRESS;
+
+ //
+ // Calculate the bios base address.
+ //
+
+ eisaSlotNumber = 0xC0000 + (dataByte * 0x4000);
+
+ if (eisaSlotNumber < 0xF0000) {
+
+ DebugPrint((1, "Aha174xConfiguration: Bios address at: %lx.\n", eisaSlotNumber));
+ (*ConfigInfo->AccessRanges)[1].RangeStart =
+ ScsiPortConvertUlongToPhysicalAddress(eisaSlotNumber);
+ (*ConfigInfo->AccessRanges)[1].RangeLength = BIOS_LENGTH;
+ (*ConfigInfo->AccessRanges)[1].RangeInMemory = TRUE;
+
+ }
+ }
+
+ return SP_RETURN_FOUND;
+
+} // end Aha174xConfiguration()
+
+
+BOOLEAN
+Aha174xInitialize(
+ IN PVOID HwDeviceExtension
+ )
+
+/*++
+
+Routine Description:
+
+ Inititialize adapter and mailbox.
+
+Arguments:
+
+ HwDeviceExtension - HBA miniport driver's adapter data storage
+
+Return Value:
+
+ TRUE - if initialization successful.
+ FALSE - if initialization unsuccessful.
+
+--*/
+
+{
+ PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
+
+ //
+ // Reset Aha174x and SCSI bus.
+ //
+
+ if (!Aha174xResetBus(deviceExtension, 0)) {
+
+ DebugPrint((1, "Aha174xInitialize: Reset bus failed\n"));
+ return FALSE;
+
+ } else {
+
+ ScsiPortNotification(ResetDetected, deviceExtension, 0);
+
+ return TRUE;
+ }
+
+} // end Aha174xInitialize()
+
+
+BOOLEAN
+Aha174xStartIo(
+ IN PVOID HwDeviceExtension,
+ IN PSCSI_REQUEST_BLOCK Srb
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called from the SCSI port driver synchronized
+ with the kernel to send an ECB or issue an immediate command.
+
+Arguments:
+
+ HwDeviceExtension - HBA miniport driver's adapter data storage
+ Srb - IO request packet
+
+Return Value:
+
+ TRUE
+
+--*/
+
+{
+ PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
+ PEISA_CONTROLLER eisaController = deviceExtension->EisaController;
+ PECB ecb;
+ PSCSI_REQUEST_BLOCK abortedSrb;
+ UCHAR opCode;
+ ULONG physicalEcb;
+ ULONG length;
+ ULONG i = 0;
+ UCHAR count = MAX_QUEUE_DEPTH;
+
+ ASSERT(Srb->SrbStatus == SRB_STATUS_PENDING);
+
+ //
+ // Get ECB from SRB.
+ //
+
+ if (Srb->Function == SRB_FUNCTION_ABORT_COMMAND) {
+
+ //
+ // Verify that SRB to abort is still outstanding.
+ //
+
+ abortedSrb = ScsiPortGetSrb(deviceExtension,
+ Srb->PathId,
+ Srb->TargetId,
+ Srb->Lun,
+ Srb->QueueTag);
+
+ if (abortedSrb != Srb->NextSrb ||
+ abortedSrb->SrbStatus != SRB_STATUS_PENDING) {
+
+ DebugPrint((1, "A174xStartIo: SRB to abort already completed\n"));
+
+ //
+ // Complete abort SRB.
+ //
+
+ Srb->SrbStatus = SRB_STATUS_ABORT_FAILED;
+
+ ScsiPortNotification(RequestComplete,
+ deviceExtension,
+ Srb);
+ //
+ // Adapter ready for next request.
+ //
+
+ ScsiPortNotification(NextRequest,
+ deviceExtension,
+ NULL);
+
+ return TRUE;
+ }
+
+ //
+ // Get ECB to abort.
+ //
+
+ ecb = Srb->NextSrb->SrbExtension;
+
+ //
+ // Set abort SRB for completion.
+ //
+
+ ecb->AbortSrb = Srb;
+
+ } else {
+
+ ecb = Srb->SrbExtension;
+
+ //
+ // Save SRB back pointer in ECB.
+ //
+
+ ecb->SrbAddress = Srb;
+ ecb->AbortSrb = NULL;
+
+ }
+
+ //
+ // Get ECB physical address.
+ //
+
+ physicalEcb =
+ ScsiPortConvertPhysicalAddressToUlong(
+ ScsiPortGetPhysicalAddress(deviceExtension, NULL, ecb, &length));
+
+ //
+ // Assume physical address is contiguous for size of ECB.
+ //
+
+ ASSERT(length >= sizeof(ECB));
+
+ switch (Srb->Function) {
+
+ case SRB_FUNCTION_EXECUTE_SCSI:
+
+ //
+ // Build ECB for regular request or request sense.
+ //
+
+ if (Srb->Cdb[0] == SCSIOP_REQUEST_SENSE) {
+ A174xBuildRequestSense(deviceExtension, Srb);
+ } else {
+ A174xBuildEcb(deviceExtension, Srb);
+ }
+
+ //
+ // Increment the request count.
+ //
+
+ count = ++deviceExtension->RequestCount[Srb->TargetId][Srb->Lun];
+
+ opCode = START_ECB;
+
+ break;
+
+ case SRB_FUNCTION_ABORT_COMMAND:
+
+ DebugPrint((1, "Aha174xStartIo: Abort request received\n"));
+
+ opCode = ABORT_ECB;
+
+ break;
+
+ default:
+
+ //
+ // Set error, complete request
+ // and signal ready for next request.
+ //
+
+ Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
+
+ ScsiPortNotification(RequestComplete,
+ deviceExtension,
+ Srb);
+
+ ScsiPortNotification(NextRequest,
+ deviceExtension,
+ NULL);
+
+ return TRUE;
+
+ } // end switch
+
+ if (!A174xSendCommand(deviceExtension,
+ (UCHAR)(opCode | Srb->TargetId),
+ physicalEcb)) {
+
+ DebugPrint((1,"Aha174xStartIo: Send command timed out\n"));
+
+ //
+ // Save the request utill a pending one completes.
+ //
+
+ deviceExtension->PendingSrb = Srb;
+
+ return(TRUE);
+
+ }
+
+ //
+ // Adapter ready for next request.
+ //
+
+ if (count < MAX_QUEUE_DEPTH) {
+
+ //
+ // Request another request for this logical unit.
+ //
+
+ ScsiPortNotification(NextLuRequest,
+ deviceExtension,
+ Srb->PathId,
+ Srb->TargetId,
+ Srb->Lun);
+
+ } else {
+
+ //
+ // Request another request for this adapter.
+ //
+
+ ScsiPortNotification(NextRequest,
+ deviceExtension,
+ Srb->PathId,
+ Srb->TargetId,
+ Srb->Lun);
+
+ }
+
+ return TRUE;
+
+} // end Aha174xStartIo()
+
+
+BOOLEAN
+Aha174xInterrupt(
+ IN PVOID HwDeviceExtension
+ )
+
+/*++
+
+Routine Description:
+
+ This is the interrupt service routine for the Aha174x SCSI adapter.
+ It reads the interrupt register to determine if the adapter is indeed
+ the source of the interrupt and clears the interrupt at the device.
+ If the adapter is interrupting because a mailbox is full, the ECB is
+ retrieved to complete the request.
+
+Arguments:
+
+ HwDeviceExtension - HBA miniport driver's adapter data storage
+
+Return Value:
+
+ TRUE if MailboxIn full
+
+--*/
+
+{
+ PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
+ PECB ecb;
+ PSCSI_REQUEST_BLOCK srb;
+ PEISA_CONTROLLER eisaController = deviceExtension->EisaController;
+ PSTATUS_BLOCK statusBlock;
+ UCHAR targetId;
+ UCHAR lun;
+ ULONG physicalEcb;
+ UCHAR interruptStatus;
+
+ //
+ // Check interrupt pending.
+ //
+
+ if (!(ScsiPortReadPortUchar(&eisaController->Status) &
+ INTERRUPT_PENDING)) {
+
+ DebugPrint((4, "Aha174xInterrupt: Spurious interrupt\n"));
+ return FALSE;
+ }
+
+ //
+ // Read interrupt status.
+ //
+
+ interruptStatus = ScsiPortReadPortUchar(
+ &eisaController->InterruptStatus);
+
+ //
+ // Get targetId
+ //
+
+ targetId = interruptStatus & 0x0F;
+
+ //
+ // Get physical address of ECB.
+ //
+
+ physicalEcb = ScsiPortReadPortUlong(&eisaController->MailBoxIn);
+
+ //
+ // Acknowledge interrupt.
+ //
+
+ ScsiPortWritePortUchar(&eisaController->Control, CLEAR_INTERRUPT);
+
+ //
+ // Check for pending requests. If there is one then start it.
+ //
+
+ if (deviceExtension->PendingSrb != NULL) {
+
+ srb = deviceExtension->PendingSrb;
+ deviceExtension->PendingSrb = NULL;
+
+ Aha174xStartIo(deviceExtension, srb);
+
+ }
+
+ switch (interruptStatus>>4) {
+
+ case ECB_COMPLETE_SUCCESS:
+ case ECB_COMPLETE_SUCCESS_RETRY:
+
+ //
+ // Get virtual ECB address.
+ //
+
+ ecb = ScsiPortGetVirtualAddress(deviceExtension, ScsiPortConvertUlongToPhysicalAddress(physicalEcb));
+
+ //
+ // Make sure this was a valid physical address.
+ //
+
+ if (ecb == NULL || ecb->SrbAddress == NULL) {
+ break;
+ }
+
+ //
+ // Get SRB from ECB.
+ //
+
+ srb = ecb->SrbAddress;
+
+ //
+ // Clear SRB from ECB.
+ //
+
+ ecb->SrbAddress = NULL;
+
+ //
+ // Update SRB statuses.
+ //
+
+ srb->SrbStatus = SRB_STATUS_SUCCESS;
+ srb->ScsiStatus = SCSISTAT_GOOD;
+
+ //
+ // If there is a peneding abort request, then complete it.
+ // This adapter does not interrupt when an abort completes.
+ // So one of three cases will occur:
+ // The abort succeeds and the command is termainated.
+ // The abort is too late and command termainates.
+ // The abort fails but the command does not terminate.
+ // The first two cases are handled by completing the abort when the
+ // command completes. The last case is handled by the abort timing
+ // out.
+ //
+
+ if (ecb->AbortSrb != NULL) {
+
+ ecb->AbortSrb->SrbStatus = SRB_STATUS_SUCCESS;
+
+ //
+ // Complete the abort request.
+ //
+
+ ScsiPortNotification(
+ RequestComplete,
+ deviceExtension,
+ ecb->AbortSrb
+ );
+
+ ecb->AbortSrb = NULL;
+ }
+
+ if (deviceExtension->RequestCount[srb->TargetId][srb->Lun]--
+ == MAX_QUEUE_DEPTH) {
+
+ //
+ // The adapter can now take another request for this device.
+ //
+
+ ScsiPortNotification(NextLuRequest,
+ deviceExtension,
+ srb->PathId,
+ srb->TargetId,
+ srb->Lun);
+
+ }
+
+ //
+ // Call notification routine for the SRB.
+ //
+
+ ScsiPortNotification(RequestComplete,
+ (PVOID)deviceExtension,
+ srb);
+
+ return TRUE;
+
+ case ECB_COMPLETE_ERROR:
+
+ //
+ // Get virtual ECB address.
+ //
+
+ ecb = ScsiPortGetVirtualAddress(deviceExtension, ScsiPortConvertUlongToPhysicalAddress(physicalEcb));
+
+ //
+ // Make sure this was a valid physical address.
+ //
+
+ if (ecb == NULL || ecb->SrbAddress == NULL) {
+ break;
+ }
+
+ //
+ // Get SRB from ECB.
+ //
+
+ srb = ecb->SrbAddress;
+
+ //
+ // Clear SRB from ECB.
+ //
+
+ ecb->SrbAddress = NULL;
+
+ //
+ // Get Status Block virtual address.
+ //
+
+ statusBlock = ScsiPortGetVirtualAddress(deviceExtension,
+ ScsiPortConvertUlongToPhysicalAddress(ecb->StatusBlockAddress));
+
+ //
+ // If there is a peneding abort request, then complete it.
+ // This adapter does not interrupt when an abort completes.
+ // So one of three cases will occur:
+ // The abort succeeds and the command is termainated.
+ // The abort is too late and command termainates.
+ // The abort fails but the command does not terminate.
+ // The first two cases are handled by completing the abort when the
+ // command completes. The last case is handled by the abort timing
+ // out.
+ //
+
+ if (ecb->AbortSrb != NULL) {
+
+ ecb->AbortSrb->SrbStatus = SRB_STATUS_SUCCESS;
+
+ //
+ // Complete the abort request.
+ //
+
+ ScsiPortNotification(
+ RequestComplete,
+ deviceExtension,
+ ecb->AbortSrb
+ );
+
+ ecb->AbortSrb = NULL;
+ }
+
+ //
+ // Update SRB status.
+ //
+
+ A174xMapStatus(deviceExtension, srb, statusBlock);
+
+ if (deviceExtension->RequestCount[srb->TargetId][srb->Lun]--
+ == MAX_QUEUE_DEPTH) {
+
+ //
+ // The adapter can now take another request for this device.
+ //
+
+ ScsiPortNotification(NextLuRequest,
+ deviceExtension,
+ srb->PathId,
+ srb->TargetId,
+ srb->Lun);
+
+ }
+
+ //
+ // Call notification routine for the SRB.
+ //
+
+ ScsiPortNotification(RequestComplete,
+ (PVOID)deviceExtension,
+ srb);
+
+ return TRUE;
+
+ case IMMEDIATE_COMMAND_SUCCESS:
+
+ DebugPrint((2,"Aha174xInterrupt: Immediate command completed\n"));
+ return TRUE;
+
+ case ASYNCHRONOUS_EVENT_NOTIFICATION:
+
+ //
+ // Check if bus was reset.
+ //
+
+ if ((physicalEcb >> 24) == 0x23) {
+
+ //
+ // Clear the reqeust counts.
+ //
+
+ for (targetId = 0; targetId < 8; targetId++) {
+ for (lun = 0; lun < 8; lun++) {
+
+ deviceExtension->RequestCount[targetId][lun] = 0;
+ }
+ }
+
+ //
+ // Complete all outstanding requests.
+ //
+
+ ScsiPortCompleteRequest(deviceExtension,
+ 0,
+ SP_UNTAGGED,
+ 0,
+ SRB_STATUS_BUS_RESET);
+
+
+ //
+ // Notify operating system of SCSI bus reset.
+ //
+
+ ScsiPortNotification(ResetDetected,
+ deviceExtension,
+ NULL);
+ }
+
+ return TRUE;
+
+ case IMMEDIATE_COMMAND_ERROR:
+ default:
+
+ DebugPrint((1, "A174xInterrupt: Unrecognized interrupt status %x\n",
+ interruptStatus));
+
+ //
+ // Log the error.
+ //
+
+ ScsiPortLogError(
+ HwDeviceExtension,
+ NULL,
+ 0,
+ deviceExtension->HostTargetId,
+ 0,
+ SP_INTERNAL_ADAPTER_ERROR,
+ 1 << 16 | interruptStatus
+ );
+
+ return TRUE;
+
+ } // end switch
+
+ //
+ // A bad physcial address was return by the adapter.
+ // Log it as an error.
+ //
+
+ ScsiPortLogError(
+ HwDeviceExtension,
+ NULL,
+ 0,
+ deviceExtension->HostTargetId,
+ 0,
+ SP_INTERNAL_ADAPTER_ERROR,
+ 5 << 16 | interruptStatus
+ );
+
+ return TRUE;
+
+} // end Aha174xInterrupt()
+
+
+VOID
+A174xBuildEcb(
+ IN PHW_DEVICE_EXTENSION DeviceExtension,
+ IN PSCSI_REQUEST_BLOCK Srb
+ )
+
+/*++
+
+Routine Description:
+
+ Build ECB for Aha174x.
+
+Arguments:
+
+ DeviceExtenson
+ SRB
+
+Return Value:
+
+ Nothing.
+
+--*/
+
+{
+ PECB ecb = Srb->SrbExtension;
+ PSTATUS_BLOCK statusBlock = &ecb->StatusBlock;
+ ULONG length;
+
+ //
+ // Set ECB command.
+ //
+
+ ecb->Command = ECB_COMMAND_INITIATOR_COMMAND;
+
+ //
+ // Disable updating status block on success;
+ //
+
+ ecb->Flags[0] = ECB_FLAGS_DISABLE_STATUS_BLOCK;
+
+ //
+ // initialize ECB flags
+ //
+
+ ecb->Flags[1] = 0;
+
+ //
+ // Set transfer direction bit.
+ //
+
+ if (Srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
+
+ //
+ // Write command.
+ //
+
+ ecb->Flags[1] |= ECB_FLAGS_WRITE;
+
+ } else if (Srb->SrbFlags & SRB_FLAGS_DATA_IN) {
+
+ //
+ // Read command.
+ //
+
+ ecb->Flags[1] |= ECB_FLAGS_READ;
+ }
+
+ //
+ // Check if disconnect explicity forbidden.
+ //
+
+ if (Srb->SrbFlags & SRB_FLAGS_DISABLE_DISCONNECT) {
+
+ ecb->Flags[1] |= ECB_FLAGS_NO_DISCONNECT;
+ }
+
+ //
+ // Set LUN (bits 16, 17 and 18).
+ //
+
+ ecb->Flags[1] |= Srb->Lun;
+
+ //
+ // Set CDB length and copy to ECB.
+ //
+
+ ecb->CdbLength = Srb->CdbLength;
+ ScsiPortMoveMemory(ecb->Cdb, Srb->Cdb, Srb->CdbLength);
+
+ //
+ // Build SGL in ECB if data transfer.
+ //
+
+ if (Srb->DataTransferLength > 0) {
+ ecb->Flags[0] |= ECB_FLAGS_SCATTER_GATHER;
+ A174xBuildSgl(DeviceExtension, Srb);
+ } else {
+ ecb->SglLength = 0;
+ }
+
+ //
+ // Set status block pointer.
+ //
+
+ ecb->StatusBlockAddress =
+ ScsiPortConvertPhysicalAddressToUlong(
+ ScsiPortGetPhysicalAddress(DeviceExtension,
+ NULL,
+ statusBlock,
+ &length));
+
+ ASSERT(length >= sizeof(STATUS_BLOCK));
+
+ //
+ // Setup auto sense if necessary.
+ //
+
+ if (Srb->SenseInfoBufferLength != 0 &&
+ !(Srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE)) {
+
+ //
+ // Set the flag to enable auto sense and fill in the address and length
+ // of the sense buffer.
+ //
+
+ ecb->Flags[0] |= ECB_FLAGS_AUTO_REQUEST_SENSE;
+ ecb->SenseInfoLength = Srb->SenseInfoBufferLength;
+ ecb->SenseInfoAddress = ScsiPortConvertPhysicalAddressToUlong(
+ ScsiPortGetPhysicalAddress(DeviceExtension,
+ Srb,
+ Srb->SenseInfoBuffer,
+ &length));
+
+ ASSERT(length >= Srb->SenseInfoBufferLength);
+
+ } else {
+
+ ecb->SenseInfoLength = 0;
+ }
+
+ //
+ // Zero out next ECB, request sense info fields
+ // and statuses in status block.
+ //
+
+ ecb->NextEcb = 0;
+ statusBlock->HaStatus = 0;
+ statusBlock->TargetStatus = 0;
+
+ return;
+
+} // end A174xBuildEcb()
+
+
+VOID
+A174xBuildSgl(
+ IN PHW_DEVICE_EXTENSION DeviceExtension,
+ IN PSCSI_REQUEST_BLOCK Srb
+ )
+
+/*++
+
+Routine Description:
+
+ This routine builds a scatter/gather descriptor list for the ECB.
+
+Arguments:
+
+ DeviceExtension
+ Srb
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PVOID dataPointer = Srb->DataBuffer;
+ ULONG bytesLeft = Srb->DataTransferLength;
+ PECB ecb = Srb->SrbExtension;
+ PSGL sgl = &ecb->Sgl;
+ ULONG physicalSgl;
+ ULONG physicalAddress;
+ ULONG length;
+ ULONG descriptorCount = 0;
+
+ //
+ // Get physical SGL address.
+ //
+
+ physicalSgl = ScsiPortConvertPhysicalAddressToUlong(
+ ScsiPortGetPhysicalAddress(DeviceExtension, NULL,
+ sgl, &length));
+
+ //
+ // Assume physical memory contiguous for sizeof(SGL) bytes.
+ //
+
+ ASSERT(length >= sizeof(SGL));
+
+ //
+ // Create SGL segment descriptors.
+ //
+
+ do {
+
+ //
+ // Get physical address and length of contiguous
+ // physical buffer.
+ //
+
+ physicalAddress =
+ ScsiPortConvertPhysicalAddressToUlong(
+ ScsiPortGetPhysicalAddress(DeviceExtension,
+ Srb,
+ dataPointer,
+ &length));
+
+ //
+ // If length of physical memory is more
+ // than bytes left in transfer, use bytes
+ // left as final length.
+ //
+
+ if (length > bytesLeft) {
+ length = bytesLeft;
+ }
+
+ sgl->Descriptor[descriptorCount].Address = physicalAddress;
+ sgl->Descriptor[descriptorCount].Length = length;
+
+ //
+ // Adjust counts.
+ //
+
+ dataPointer = (PUCHAR)dataPointer + length;
+ bytesLeft -= length;
+ descriptorCount++;
+
+ } while (bytesLeft);
+
+ //
+ // Write SGL length to ECB.
+ //
+
+ ecb->SglLength = descriptorCount * sizeof(SG_DESCRIPTOR);
+
+ //
+ // Write SGL address to ECB.
+ //
+
+ ecb->PhysicalSgl = physicalSgl;
+
+ return;
+
+} // end A174xBuildSgl()
+
+
+VOID
+A174xBuildRequestSense(
+ IN PVOID HwDeviceExtension,
+ IN PSCSI_REQUEST_BLOCK Srb
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called when a request sense is detected. An adapter
+ command is then built for a request sense. This is the
+ only way to clear the contingent alligience condition that the adapter
+ is always in following a check condition.
+
+Arguments:
+
+ HwDeviceExtension - HBA miniport driver's adapter data storage
+ Srb - IO request packet
+
+Return Value:
+
+ TRUE is request succeeds.
+
+--*/
+
+{
+ PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
+ PEISA_CONTROLLER eisaController = deviceExtension->EisaController;
+ PECB ecb = Srb->SrbExtension;
+ PSTATUS_BLOCK statusBlock = &ecb->StatusBlock;
+ ULONG length;
+
+ //
+ // Set ECB command.
+ //
+
+ ecb->Command = ECB_COMMAND_READ_SENSE_INFO;
+
+ //
+ // Disable updating status block on success and enable
+ // automatic request senes.
+ //
+
+ ecb->Flags[0] = ECB_FLAGS_DISABLE_STATUS_BLOCK |
+ ECB_FLAGS_SUPPRESS_UNDERRUN;
+
+ //
+ // Set transfer direction bit.
+ //
+
+ ecb->Flags[1] = ECB_FLAGS_READ;
+
+ //
+ // Check if disconnect explicity forbidden.
+ //
+
+ if (Srb->SrbFlags & SRB_FLAGS_DISABLE_DISCONNECT) {
+
+ ecb->Flags[1] |= ECB_FLAGS_NO_DISCONNECT;
+ }
+
+ //
+ // Set LUN (bits 16, 17 and 18).
+ //
+
+ ecb->Flags[1] |= Srb->Lun;
+
+ //
+ // Set status block pointer.
+ //
+
+ ecb->StatusBlockAddress =
+ ScsiPortConvertPhysicalAddressToUlong(
+ ScsiPortGetPhysicalAddress(deviceExtension,
+ NULL,
+ statusBlock,
+ &length));
+
+ //
+ // Set request sense address and length.
+ //
+
+ ecb->SenseInfoAddress = ScsiPortConvertPhysicalAddressToUlong(
+ ScsiPortGetPhysicalAddress(deviceExtension,
+ Srb,
+ Srb->DataBuffer,
+ &length));
+
+ ASSERT(length >= Srb->DataTransferLength);
+
+ ecb->SenseInfoLength = (UCHAR) Srb->DataTransferLength;
+
+ //
+ // Zero out next ECB, request sense info fields
+ // and statuses in status block.
+ //
+
+ ecb->NextEcb = 0;
+ statusBlock->HaStatus = 0;
+ statusBlock->TargetStatus = 0;
+
+ return;
+
+} // end A174xBuildRequestSense()
+
+
+BOOLEAN
+A174xSendCommand(
+ IN PHW_DEVICE_EXTENSION DeviceExtension,
+ IN UCHAR OperationCode,
+ IN ULONG Address
+ )
+
+/*++
+
+Routine Description:
+
+ Send ECB or immediate command to AHA174X.
+
+Arguments:
+
+ HwDeviceExtension - HBA miniport driver's adapter data storage
+ OperationCode - value to be written to attention register
+ Address - ECB address or immediate command
+
+Return Value:
+
+ True if command sent.
+ False if adapter never reached 'ready for next command' state.
+
+--*/
+
+{
+ PEISA_CONTROLLER eisaController = DeviceExtension->EisaController;
+ ULONG i;
+
+ for (i=0; i<10; i++) {
+
+ UCHAR status;
+
+ status = ScsiPortReadPortUchar(&eisaController->Status);
+
+ if ((status & MAILBOX_OUT_EMPTY) &&
+ !(status & ADAPTER_BUSY)) {
+
+ //
+ // Adapter ready for next command.
+ //
+
+ break;
+
+ } else {
+
+ //
+ // Stall 1 microsecond before trying again.
+ //
+
+ ScsiPortStallExecution(1);
+ }
+ }
+
+ if (i == 10) {
+
+ return FALSE;
+ }
+
+ //
+ // Write ECB address or immediate command.
+ //
+
+ ScsiPortWritePortUlong(&eisaController->MailBoxOut, Address);
+
+ //
+ // Write operation code to attention register.
+ //
+
+ ScsiPortWritePortUchar(&eisaController->Attention, OperationCode);
+
+ return TRUE;
+
+} // end A174xSendCommand()
+
+BOOLEAN
+Aha174xResetBus(
+ IN PVOID HwDeviceExtension,
+ IN ULONG PathId
+)
+
+/*++
+
+Routine Description:
+
+ Reset Aha174x SCSI adapter and SCSI bus.
+
+Arguments:
+
+ HwDeviceExtension - HBA miniport driver's adapter data storage
+
+Return Value:
+
+ Nothing.
+
+--*/
+
+{
+ PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
+ PEISA_CONTROLLER eisaController = deviceExtension->EisaController;
+ ULONG j;
+ UCHAR targetId;
+ UCHAR lun;
+
+
+ UNREFERENCED_PARAMETER(PathId);
+
+ DebugPrint((2,"ResetBus: Reset Aha174x and SCSI bus\n"));
+
+ //
+ // Clean up pending requests.
+ //
+
+ if (deviceExtension->PendingSrb) {
+
+ //
+ // Notify the port driver that another request can be accepted.
+ //
+
+ ScsiPortNotification(NextRequest, deviceExtension);
+
+ //
+ // Clear the pending request. It will be completed by
+ // ScsiPortCompleteRequest.
+ //
+
+ deviceExtension->PendingSrb = NULL;
+
+ }
+
+ //
+ // Clear the reqeust counts.
+ //
+
+ for (targetId = 0; targetId < 8; targetId++) {
+ for (lun = 0; lun < 8; lun++) {
+
+ deviceExtension->RequestCount[targetId][lun] = 0;
+ }
+ }
+
+ //
+ // Complete all outstanding requests.
+ //
+
+ ScsiPortCompleteRequest(deviceExtension,
+ 0,
+ SP_UNTAGGED,
+ SP_UNTAGGED,
+ SRB_STATUS_BUS_RESET);
+
+ targetId = deviceExtension->HostTargetId;
+
+ //
+ // Allow the adapter card to settle.
+ //
+
+ ScsiPortStallExecution(75000);
+ ScsiPortReadPortUchar(&eisaController->Status);
+ ScsiPortStallExecution(1);
+
+ if (!A174xSendCommand(deviceExtension,
+ (UCHAR)(IMMEDIATE_COMMAND | targetId),
+ ECB_IMMEDIATE_RESET)) {
+
+ //
+ // Timed out waiting for adapter to become ready.
+ //
+
+ ScsiPortLogError(
+ deviceExtension,
+ NULL,
+ 0,
+ deviceExtension->HostTargetId,
+ 0,
+ SP_INTERNAL_ADAPTER_ERROR,
+ 4 << 16
+ );
+
+ //
+ // Adapter never reached state to receive command.
+ // Try a hard reset by wiggling the control line.
+ //
+
+ ScsiPortWritePortUchar(&eisaController->Control, HARD_RESET);
+
+ //
+ // Wait at least 10 microseconds.
+ //
+
+ ScsiPortStallExecution(10);
+
+ //
+ // Clear the reset line now that it has been held for 10 us.
+ //
+
+ ScsiPortWritePortUchar(&eisaController->Control, 0);
+
+ //
+ // Write the attention register to wake up the firmware so that
+ // it will clear the busy line in the status register.
+ // The attention value written (0) is ignored by the controller
+ // but will wakeup the firmware.
+ //
+
+ ScsiPortStallExecution(20000); // Add a little delay
+ ScsiPortWritePortUchar(&eisaController->Attention, 0);
+
+ //
+ // Wait for busy to go low.
+ //
+
+ j = 0;
+ while (ScsiPortReadPortUchar(&eisaController->Status) & ADAPTER_BUSY) {
+
+ j++;
+ if (j > 200000) {
+
+ //
+ // Busy has not gone low. Assume the card is gone.
+ // Log the error and fail the request.
+ //
+
+
+ ScsiPortLogError(
+ deviceExtension,
+ NULL,
+ 0,
+ deviceExtension->HostTargetId,
+ 0,
+ SP_INTERNAL_ADAPTER_ERROR,
+ 3 << 16
+ );
+
+ return FALSE;
+
+ }
+
+ ScsiPortStallExecution(10);
+ }
+ }
+
+ return TRUE;
+
+} // end Aha174xResetBus()
+
+
+VOID
+A174xMapStatus(
+ IN PHW_DEVICE_EXTENSION DeviceExtension,
+ IN PSCSI_REQUEST_BLOCK Srb,
+ IN PSTATUS_BLOCK StatusBlock
+ )
+
+/*++
+
+Routine Description:
+
+ Translate Aha174x error to SRB error.
+
+Arguments:
+
+ SRB
+ Status block for request completing with error.
+
+Return Value:
+
+ Updated SRB
+
+--*/
+
+{
+ ULONG logError = 0;
+ UCHAR srbStatus;
+ PECB ecb = Srb->SrbExtension;
+
+
+ DebugPrint((2,
+ "A174xMapStatus: Status word is %x\n",
+ StatusBlock->StatusWord));
+
+ if (StatusBlock->TargetStatus == SCSISTAT_CHECK_CONDITION) {
+
+ //
+ // A check condition occured. Set the srb status and process the
+ // auto sense data.
+ //
+
+ Srb->SrbStatus = SRB_STATUS_ERROR;
+
+ //
+ // Set target SCSI status in SRB.
+ //
+
+ Srb->ScsiStatus = StatusBlock->TargetStatus;
+
+ //
+ // Update SRB with actual bytes transferred.
+ //
+
+ Srb->DataTransferLength -= StatusBlock->ResidualByteCount;
+
+ if (StatusBlock->StatusWord & SB_STATUS_SENSE_INFORMATION) {
+
+ //
+ // Indicate the sense information is valid and update the length.
+ //
+
+ Srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
+ Srb->SenseInfoBufferLength = StatusBlock->RequestSenseLength;
+ }
+
+ return;
+ }
+
+ switch (StatusBlock->HaStatus) {
+
+ case SB_HASTATUS_SELECTION_TIMEOUT:
+ srbStatus = SRB_STATUS_SELECTION_TIMEOUT;
+ break;
+
+ case SB_HASTATUS_DATA_OVERUNDER_RUN:
+ DebugPrint((1,"A174xMapStatus: Data over/underrun\n"));
+
+ //
+ // Update SRB with actual bytes transferred.
+ //
+
+ Srb->DataTransferLength -= StatusBlock->ResidualByteCount;
+
+ srbStatus = SRB_STATUS_DATA_OVERRUN;
+ break;
+
+ case SB_HASTATUS_UNEXPECTED_BUS_FREE:
+ DebugPrint((1,"A174xMapStatus: Unexpected bus free\n"));
+ logError = SP_PROTOCOL_ERROR;
+ srbStatus = SRB_STATUS_UNEXPECTED_BUS_FREE;
+ break;
+
+ case SB_HASTATUS_INVALID_BUS_PHASE:
+ DebugPrint((1,"A174xMapStatus: Invalid bus phase\n"));
+ logError = SP_PROTOCOL_ERROR;
+ srbStatus = SRB_STATUS_PHASE_SEQUENCE_FAILURE;
+ break;
+
+ case SB_HASTATUS_TARGET_NOT_USED:
+ DebugPrint((1,"A174xMapStatus: Target not used\n"));
+ srbStatus = SRB_STATUS_NO_DEVICE;
+ break;
+
+ case SB_HASTATUS_INVALID_ECB:
+ DebugPrint((1,"A174xMapStatus: Invalid ECB\n"));
+ logError = SP_INTERNAL_ADAPTER_ERROR;
+ srbStatus = SRB_STATUS_INVALID_REQUEST;
+ break;
+
+ case SB_HASTATUS_ADAPTER_HARDWARE_ERROR:
+ DebugPrint((1,"A174xMapStatus: Hardware error\n"));
+ logError = SP_INTERNAL_ADAPTER_ERROR;
+ srbStatus = SRB_STATUS_ERROR;
+ break;
+
+ case SB_HASTATUS_ADAPTER_RESET_BUS:
+ DebugPrint((1,"A174xMapStatus: Adapter reset bus\n"));
+ srbStatus = SRB_STATUS_BUS_RESET;
+ break;
+
+ case SB_HASTATUS_DEVICE_RESET_BUS:
+ DebugPrint((1,"A174xMapStatus: Device reset bus\n"));
+ srbStatus = SRB_STATUS_BUS_RESET;
+ break;
+
+ case SB_HASTATUS_CHECKSUM_FAILURE:
+ DebugPrint((1,"A174xMapStatus: Checksum failure\n"));
+ logError = SP_INTERNAL_ADAPTER_ERROR;
+ srbStatus = SRB_STATUS_ERROR;
+ break;
+
+ case SB_HASTATUS_ADAPTER_ABORTED:
+ DebugPrint((1,"A174xMapStatus: Adapter aborted\n"));
+ srbStatus = SRB_STATUS_ABORTED;
+ break;
+
+ case SB_HASTATUS_HOST_ABORTED:
+ DebugPrint((1,"A174xMapStatus: Host aborted\n"));
+ srbStatus = SRB_STATUS_ABORTED;
+ break;
+
+ case SB_HASTATUS_FW_NOT_DOWNLOADED:
+ DebugPrint((1,"A174xMapStatus: Firmware not downloaded\n"));
+ logError = SP_INTERNAL_ADAPTER_ERROR;
+ srbStatus = SRB_STATUS_ERROR;
+ break;
+
+ case SB_HASTATUS_INVALID_SGL:
+ DebugPrint((1,"A174xMapStatus: Invalid SGL\n"));
+ logError = SP_INTERNAL_ADAPTER_ERROR;
+ srbStatus = SRB_STATUS_INVALID_REQUEST;
+ break;
+
+ case SB_HASTATUS_REQUEST_SENSE_FAILED:
+ DebugPrint((1,"A174xMapStatus: Request sense failed\n"));
+ srbStatus = SRB_STATUS_ERROR;
+ break;
+
+ default:
+
+ srbStatus = SRB_STATUS_ERROR;
+
+ //
+ // Check status block word.
+ //
+
+ if (StatusBlock->StatusWord & SB_STATUS_NO_ERROR) {
+
+ //
+ // This should never happen as this routine is only
+ // called when there is an error.
+ //
+
+ DebugPrint((1,"A174xMapStatus: No error\n"));
+ srbStatus = SRB_STATUS_SUCCESS;
+ break;
+
+ }
+
+ //
+ // Check for underrun.
+ //
+
+ if (StatusBlock->StatusWord & SB_STATUS_DATA_UNDERRUN) {
+
+ DebugPrint((1,
+ "A174xMapStatus: Data underrun indicated in status word\n"));
+
+ //
+ // Update SRB with actual bytes transferred.
+ //
+
+ Srb->DataTransferLength -= StatusBlock->ResidualByteCount;
+ break;
+ }
+
+ //
+ // Check for overrun.
+ //
+
+ if (StatusBlock->StatusWord & SB_STATUS_DATA_OVERRUN) {
+
+ DebugPrint((1,
+ "A174xMapStatus: Data overrun indicate in status word\n"));
+ logError = SP_PROTOCOL_ERROR;
+ break;
+ }
+
+ //
+ // Check for initialization required.
+ //
+
+ if (StatusBlock->StatusWord & SB_STATUS_INIT_REQUIRED) {
+ DebugPrint((1,
+ "A174xMapStatus: Initialization required\n"));
+ break;
+ }
+
+ //
+ // Check for contingent allegience condition. If this happens
+ // something is very wrong (because autorequest sense was indicated).
+ //
+
+ if (StatusBlock->StatusWord & SB_STATUS_EXT_CONT_ALLEGIANCE) {
+
+ DebugPrint((1,
+ "A174xMapStatus: Contingent allegiance condition\n"));
+
+ ASSERT(0);
+ }
+
+ if (StatusBlock->StatusWord & SB_STATUS_MAJOR_ERROR) {
+
+ DebugPrint((1,
+ "A174xMapStatus: Major error indicated in status word\n"));
+ break;
+ }
+
+ logError = SP_INTERNAL_ADAPTER_ERROR;
+ break;
+
+ } // end switch ...
+
+ if (logError != 0) {
+
+ //
+ // Log error.
+ //
+
+ ScsiPortLogError(
+ DeviceExtension,
+ Srb,
+ Srb->PathId,
+ Srb->TargetId,
+ Srb->Lun,
+ logError,
+ 2 << 16 | StatusBlock->HaStatus
+ );
+
+ }
+
+ //
+ // Set SRB status.
+ //
+
+ Srb->SrbStatus = srbStatus;
+
+ //
+ // Set target SCSI status in SRB.
+ //
+
+ Srb->ScsiStatus = StatusBlock->TargetStatus;
+
+ return;
+
+} // end A174xMapStatus()
diff --git a/private/ntos/fw/alpha/jensen/alpha/chkstall.c b/private/ntos/fw/alpha/jensen/alpha/chkstall.c
new file mode 100644
index 000000000..01f1d224f
--- /dev/null
+++ b/private/ntos/fw/alpha/jensen/alpha/chkstall.c
@@ -0,0 +1,142 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ chkstall.c
+
+Abstract:
+
+ This is used to evalute fwstallexecution.
+
+Author:
+
+ John DeRosa 15-April-1993
+
+Environment:
+
+
+Revision History:
+
+--*/
+
+#include "fwp.h"
+#include "string.h"
+#include "jnvendor.h"
+#include "iodevice.h"
+
+//
+// The indicator of a bad Firmware stack for _RtlCheckStack
+//
+
+ULONG FwRtlStackPanic;
+
+#if 0
+
+//
+// This is needed for a reference in ntcrt.
+//
+
+VOID
+DbgBreakPoint(
+ VOID
+ )
+{
+ VenPrint ("\r\n\r\n?? INTERNAL ERROR --- CALL DEC FIELD SERVICE.\r\n");
+ while (TRUE) {
+ }
+}
+
+#endif
+
+
+VOID
+main (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG Count;
+ UCHAR Character;
+ ARC_STATUS Status;
+
+ FwRtlStackPanic = 0;
+
+ VenPrint("Doing a 5 second loop...");
+ VenStallExecution(1000000);
+ VenPrint("3... ");
+ VenStallExecution(1000000);
+ VenPrint("2... ");
+ VenStallExecution(1000000);
+ VenPrint("1... ");
+ VenStallExecution(1000000);
+ VenPrint("\r\nGO!\r\n");
+ VenStallExecution(5 * 1000 * 1000);
+ VenPrint("********************* STOP ********************\r\n\n\n");
+ VenStallExecution(5 * 1000 * 1000);
+
+ VenPrint("Doing a 10 second loop...");
+ VenStallExecution(1000000);
+ VenPrint("3... ");
+ VenStallExecution(1000000);
+ VenPrint("2... ");
+ VenStallExecution(1000000);
+ VenPrint("1... ");
+ VenStallExecution(1000000);
+ VenPrint("\r\nGO!\r\n");
+ VenStallExecution(10 * 1000 * 1000);
+ VenPrint("********************* STOP ********************\r\n\n\n");
+ VenStallExecution(5 * 1000 * 1000);
+
+ VenPrint("Doing a 20 second loop...");
+ VenStallExecution(1000000);
+ VenPrint("3... ");
+ VenStallExecution(1000000);
+ VenPrint("2... ");
+ VenStallExecution(1000000);
+ VenPrint("1... ");
+ VenStallExecution(1000000);
+ VenPrint("\r\nGO!\r\n");
+ VenStallExecution(20 * 1000 * 1000);
+ VenPrint("********************* STOP ********************\r\n\n\n");
+ VenStallExecution(5 * 1000 * 1000);
+
+ VenPrint("Doing a 40 second loop...");
+ VenStallExecution(1000000);
+ VenPrint("3... ");
+ VenStallExecution(1000000);
+ VenPrint("2... ");
+ VenStallExecution(1000000);
+ VenPrint("1... ");
+ VenStallExecution(1000000);
+ VenPrint("\r\nGO!\r\n");
+ VenStallExecution(40 * 1000 * 1000);
+ VenPrint("********************* STOP ********************\r\n\n\n");
+ VenStallExecution(5 * 1000 * 1000);
+
+ VenPrint("Press any key to return.");
+
+ if ((Status = ArcRead(ARC_CONSOLE_INPUT, &Character, 1, &Count)) != ESUCCESS) {
+ VenPrint1("? Can not read keyboard. Status = 0x%x\r\n", Status);
+ VenStallExecution(3000000);
+ }
+
+ return;
+
+
+}
diff --git a/private/ntos/fw/alpha/jensen/alpha/jenstubs.c b/private/ntos/fw/alpha/jensen/alpha/jenstubs.c
new file mode 100644
index 000000000..a754d7a1c
--- /dev/null
+++ b/private/ntos/fw/alpha/jensen/alpha/jenstubs.c
@@ -0,0 +1,46 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ jenstubs.c
+
+Abstract:
+
+ This module contains Jensen HAL stubs.
+
+ This must be included by any link that includes hal0jens\alpha\jxioacc.s.
+
+Author:
+
+ John DeRosa 15-June-1993
+
+Environment:
+
+
+Revision History:
+
+--*/
+
+#include "fwp.h"
+
+//
+// The code in tbaqva.c is not prepared for I/O addresses above 32MB.
+// But the HalpHaeTable array is needed to avoid undefined references in
+// \nt\private\ntos\nthals\hal0jens\alpha\jxioacc.s.
+//
+
+//
+// The HaeIndex, used in creating QVAs for EISA memory space.
+//
+//ULONG HaeIndex;
+
+//
+// This is the HAE table. The first table entry is used to map the lowest
+// 32MB in a Jensen system. The second entry is used to map the next 32MB
+// entry so that graphics cards, etc., will work.
+//
+
+//CHAR HalpHaeTable[4] = { 0, 1, 0, 0 };
+CHAR HalpHaeTable[4] = { 0, 0, 0, 0 };
diff --git a/private/ntos/fw/alpha/jensen/alpha/jnfs.c b/private/ntos/fw/alpha/jensen/alpha/jnfs.c
new file mode 100644
index 000000000..9bc931260
--- /dev/null
+++ b/private/ntos/fw/alpha/jensen/alpha/jnfs.c
@@ -0,0 +1,413 @@
+/*++
+
+Copyright (c) 1992, 1993 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ jnfs.c
+
+Abstract:
+
+ The main module for the Jensen FailSafe Booter, which re-attempts
+ the update of the Jensen FlashFile ROM after a power-fail.
+
+
+Author:
+
+ John DeRosa 14-October-1992
+
+ Parts of this were lifted from the Jensen firmware, which was
+ a port of the Jazz firmware, which was written by Microsoft Corporation.
+
+
+Environment:
+
+
+Revision History:
+
+--*/
+
+#include "fwp.h"
+#include "iodevice.h"
+#include "led.h"
+#include "selftest.h"
+#include "jnfs.h"
+#include "fwpexcpt.h"
+#include "fwstring.h"
+
+int errno; // For C library functions
+
+PRTL_ALLOCATE_STRING_ROUTINE RtlAllocateStringRoutine =
+ (PRTL_ALLOCATE_STRING_ROUTINE)FwAllocatePool;
+PRTL_FREE_STRING_ROUTINE RtlFreeStringRoutine = FwpFreeStub;
+
+// Number of processor cycles per microsecond.
+ULONG CyclesPerMicrosecond;
+
+// This variable is initialized to the size of the memory in bytes.
+ULONG MemorySize;
+
+
+
+//
+// This receives the type of video card installed into the system.
+// It is a static because memory is intialized near the bottom of the
+// program execute calling chain (FwExecute, FwPrivateExecute, FwResetMemory,
+// FwInitializeMemory), and the calling interface to FwExecute is
+// frozen by the ARCS specification.
+//
+// This is valid only on a successful intialization of the graphics card.
+//
+ALPHA_VIDEO_TYPE VideoType;
+
+// The indicator of a bad Firmware stack for _RtlCheckStack
+ULONG FwRtlStackPanic;
+
+
+//
+// Declare function prototypes.
+//
+
+VOID
+JnFsUpgradeSystem (
+ VOID
+ );
+
+VOID
+PutLedDisplay(
+ IN UCHAR Value
+ );
+
+ULONG
+RomInitISP (
+ VOID
+ );
+
+VOID
+WildZeroMemory(
+ ULONG StartAddress,
+ ULONG Size
+ );
+
+VOID
+FailSafeEntry(
+ IN ULONG Unused0,
+ IN PFW_PROCESSOR_INFORMATION Unused1,
+ IN PFW_SYSTEM_INFORMATION SystemInfo
+ )
+/*++
+
+Routine Description:
+
+ This function gets control from the serial ROM if the serial ROM
+ detects a corrupted VMS Console boot image. (In actuality, the
+ serial ROM passes control the the linked firmware PALcode, which
+ passes control to this function.)
+
+
+Arguments:
+
+ Unused0, This keeps the PALcode interface identical to
+ Unused1 the firmware.
+
+ SystemInfo Contains Alpha_AXP information from the PALcode.
+ Since this module is only executed on a hard reset,
+ there is no need to check the "Cause" argument.
+
+Return Value:
+
+ Never returns.
+
+--*/
+
+{
+ UNREFERENCED_PARAMETER(Unused0);
+ UNREFERENCED_PARAMETER(Unused1);
+
+ FwRtlStackPanic = 0;
+
+ // Register exception handler with the firmware PALcode
+ RegisterExceptionHandler();
+
+ // Clear out upper EISA address bits.
+ WRITE_PORT_UCHAR((PUCHAR)HAE, 0x0);
+
+ switch (SystemInfo->SystemCycleClockPeriod) {
+
+ //
+ // A bad cycle clock period would cause a system hang.
+ //
+ case 0:
+ case 8000:
+ default:
+ CyclesPerMicrosecond = 125 + 1;
+ break;
+
+ //
+ // This is an AX04 SROM bug: the number for a 6.667ns machine is
+ // passed in as 6600, not 6667.
+ //
+ case 6600:
+ case 6667:
+ CyclesPerMicrosecond = 150 + 1;
+ break;
+ }
+
+ // Initialize MemorySize to the size of memory in MegaBytes.
+ MemorySize = SystemInfo->MemorySizeInBytes;
+
+
+ //
+ // Set interrupt lines to a known state.
+ //
+
+ WRITE_PORT_UCHAR((PUCHAR)&SP1_WRITE->ModemControl,0x08);
+ WRITE_PORT_UCHAR((PUCHAR)&SP2_WRITE->ModemControl,0x08);
+ WRITE_PORT_UCHAR((PUCHAR)&FLOPPY_WRITE->DigitalOutput,0x08);
+ READ_PORT_UCHAR((PUCHAR)&PARALLEL_READ->Status);
+
+ //
+ // Initialize the system parameter block.
+ //
+
+ SYSTEM_BLOCK->Signature = 0x53435241;
+ SYSTEM_BLOCK->Length = sizeof(SYSTEM_PARAMETER_BLOCK);
+ SYSTEM_BLOCK->Version = ARC_VERSION;
+ SYSTEM_BLOCK->Revision = ARC_REVISION;
+ SYSTEM_BLOCK->RestartBlock = NULL;
+ SYSTEM_BLOCK->DebugBlock = NULL;
+
+ SYSTEM_BLOCK->FirmwareVectorLength = (ULONG)MaximumRoutine * sizeof(ULONG);
+ SYSTEM_BLOCK->FirmwareVector =
+ (PVOID)((PUCHAR)SYSTEM_BLOCK + sizeof(SYSTEM_PARAMETER_BLOCK));
+ SYSTEM_BLOCK->VendorVectorLength = (ULONG)MaximumVendorRoutine * sizeof(ULONG);
+ SYSTEM_BLOCK->VendorVector =
+ (PVOID)((PUCHAR)SYSTEM_BLOCK->FirmwareVector +
+ SYSTEM_BLOCK->FirmwareVectorLength);
+
+ SerialBootSetup(COMPORT1_VIRTUAL_BASE);
+ SerialBootSetup(COMPORT2_VIRTUAL_BASE); // This may not be needed.
+
+ //
+ // If: the configuration bit is set, or
+ // the video card initialization fails,
+ // ...output to the serial line. Otherwise, output to video.
+ //
+
+ if (DisplayBootInitialize(&VideoType) != ESUCCESS) {
+ SerialOutput = TRUE;
+ FwClearScreen();
+ } else {
+ // Video is ready to display messages.
+ DisplayOutput = TRUE;
+ }
+
+
+ //
+ // If: the keyboard controller initialization fails, or
+ // the keyboard initialization fails,
+ // ...send an error message to the output device and direct future output
+ // to the serial port.
+ //
+
+ if (InitKeyboardController() || InitKeyboard()) {
+ FwPrint(ST_ALL_IO_TO_SERIAL_LINES_MSG);
+ DisplayOutput = FALSE;
+ SerialOutput = TRUE;
+ }
+
+
+ PutLedDisplay(LED_VIDEO_OK);
+
+ //
+ // hang on error
+ //
+
+ while (RomInitISP()) {
+ }
+
+
+#if 0
+
+ //
+ // This is believed to not be necessary.
+ //
+
+ //
+ // Zero unused memory.
+ //
+ // This is dependent on the firmware memory map.
+ // This could be made more independent via using #define's.
+ //
+
+ WildZeroMemory(
+ (KSEG0_BASE | 0x0),
+ (FW_BOTTOM_ADDRESS - 0x40000)
+ );
+
+ WildZeroMemory(
+ (KSEG0_BASE | FW_TOP_ADDRESS),
+ (MemorySize - FW_TOP_ADDRESS)
+ );
+
+#endif
+
+ //
+ // Now try to complete the upgrade.
+ //
+
+ JnFsUpgradeSystem();
+
+ //
+ // Hang if we come back.
+ //
+
+ for (;;) {
+ PutLedDisplay(LED_OMEGA);
+ }
+
+}
+
+VOID
+PutLedDisplay(
+ IN UCHAR Value
+ )
+/*++
+
+Routine Description:
+
+ This displays a 0--F in the single hexadecimal digit display in
+ Jensen.
+
+Arguments:
+
+ Value The lower four bits of this will be displayed
+ in the Jensen LED.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ WRITE_PORT_UCHAR ((PUCHAR)SYSCTL,
+ (READ_PORT_UCHAR((PUCHAR)SYSCTL) & 0xf0)
+ |
+ (Value & 0x0f)
+ );
+ }
+
+ULONG
+RomInitISP (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the EISA interrupt controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns the number of errors found.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ UCHAR InterruptLevel;
+ //
+ // Initialize the EISA interrupt controller. There are two cascaded
+ // interrupt controllers, each of which must initialized with 4 initialize
+ // control words.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ WRITE_PORT_UCHAR((PUCHAR)&EISA_CONTROL->Interrupt1ControlPort0,DataByte);
+ WRITE_PORT_UCHAR((PUCHAR)&EISA_CONTROL->Interrupt2ControlPort0,DataByte);
+
+ //
+ // The second intitialization control word sets the interrupt vector to
+ // 0-15.
+ //
+ DataByte = 0;
+
+ WRITE_PORT_UCHAR((PUCHAR)&EISA_CONTROL->Interrupt1ControlPort1,DataByte);
+
+ DataByte = 0x08;
+
+ WRITE_PORT_UCHAR((PUCHAR)&EISA_CONTROL->Interrupt2ControlPort1,DataByte);
+
+ //
+ // The third initialization control word set the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a numeric.
+ //
+
+ DataByte = 1 << SLAVE_IRQL_LEVEL;
+
+ WRITE_PORT_UCHAR((PUCHAR)&EISA_CONTROL->Interrupt1ControlPort1,DataByte);
+
+ DataByte = SLAVE_IRQL_LEVEL;
+
+ WRITE_PORT_UCHAR((PUCHAR)&EISA_CONTROL->Interrupt2ControlPort1,DataByte);
+
+ //
+ // The fourth initialization control word is used to specify normal
+ // end-of-interrupt mode and not special-fully-nested mode.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1;
+
+ WRITE_PORT_UCHAR((PUCHAR)&EISA_CONTROL->Interrupt1ControlPort1,DataByte);
+ WRITE_PORT_UCHAR((PUCHAR)&EISA_CONTROL->Interrupt2ControlPort1,DataByte);
+
+
+ //
+ // Mask all the interrupts.
+ //
+ WRITE_PORT_UCHAR((PUCHAR)&EISA_CONTROL->Interrupt1ControlPort1,0xFF);
+ WRITE_PORT_UCHAR((PUCHAR)&EISA_CONTROL->Interrupt2ControlPort1,0xFF);
+
+
+#if 0 // Jazz code
+ //
+ // Check that the interrupt level is 7 (i.e. no interrupt is pending)
+ //
+ InterruptLevel=READ_PORT_UCHAR(&DMA_CONTROL->InterruptAcknowledge);
+ InterruptLevel=READ_PORT_UCHAR(&DMA_CONTROL->InterruptAcknowledge);
+
+ if (InterruptLevel == 0x07) {
+ return 0;
+ } else {
+ return 1;
+ }
+#else
+
+ // Alpha/Jensen code
+
+ //
+ // Check that no interrupts are pending.
+ //
+
+ WRITE_PORT_UCHAR((PUCHAR)&EISA_CONTROL->Interrupt1ControlPort0, 0xA);
+ InterruptLevel = READ_PORT_UCHAR((PUCHAR)&EISA_CONTROL->Interrupt1ControlPort0);
+ WRITE_PORT_UCHAR((PUCHAR)&EISA_CONTROL->Interrupt2ControlPort0, 0xA);
+ InterruptLevel |= READ_PORT_UCHAR((PUCHAR)&EISA_CONTROL->Interrupt2ControlPort0);
+
+ return(InterruptLevel);
+#endif
+
+}
diff --git a/private/ntos/fw/alpha/jensen/alpha/jnsetcfg.c b/private/ntos/fw/alpha/jensen/alpha/jnsetcfg.c
new file mode 100644
index 000000000..c52f052c8
--- /dev/null
+++ b/private/ntos/fw/alpha/jensen/alpha/jnsetcfg.c
@@ -0,0 +1,1073 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ jnsetcfg.c
+
+Abstract:
+
+ This module contains the code to make the configuration
+ data structures in the Jensen Prom.
+
+
+Author:
+
+ John DeRosa 31-July-1992.
+
+ This module, and the entire setup program, was based on the jzsetup
+ program written by David M. Robinson (davidro) of Microsoft, dated
+ 9-Aug-1991.
+
+
+Revision History:
+
+--*/
+
+#include "fwp.h"
+#include "jnsnvdeo.h"
+//#include "jnsnrtc.h"
+#include "string.h"
+#include "iodevice.h"
+#include "jnvendor.h"
+#include "oli2msft.h"
+#include "inc.h"
+
+
+VOID
+JzMakeComponent (
+ PCONFIGURATION_COMPONENT Component,
+ CONFIGURATION_CLASS Class,
+ CONFIGURATION_TYPE Type,
+ BOOLEAN ReadOnly,
+ BOOLEAN Removable,
+ BOOLEAN ConsoleIn,
+ BOOLEAN ConsoleOut,
+ BOOLEAN Input,
+ BOOLEAN Output,
+ ULONG Key,
+ ULONG ConfigurationDataLength,
+ PCHAR Identifier
+ )
+
+/*++
+
+Routine Description:
+
+ This routine fills in a configuration component structure.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // Set values that are constant for all entries.
+ //
+
+ Component->Version = ARC_VERSION;
+ Component->Revision = ARC_REVISION;
+ Component->AffinityMask = 0xffffffff;
+ Component->Flags.Failed = 0;
+
+ //
+ // Fill out the structure.
+ //
+
+ Component->Class = Class;
+ Component->Type = Type;
+ Component->Flags.ReadOnly = ReadOnly ? 1 : 0;
+ Component->Flags.Removable = Removable ? 1 : 0;
+ Component->Flags.ConsoleIn = ConsoleIn ? 1 : 0;
+ Component->Flags.ConsoleOut = ConsoleOut ? 1 : 0;
+ Component->Flags.Input = Input ? 1 : 0;
+ Component->Flags.Output = Output ? 1 : 0;
+ Component->Key = Key;
+ Component->ConfigurationDataLength = ConfigurationDataLength;
+ if (Identifier != NULL) {
+ Component->IdentifierLength = strlen(Identifier) + 1;
+ } else {
+ Component->IdentifierLength = 0;
+ }
+ Component->Identifier = Identifier;
+
+ return;
+}
+
+
+ULONG
+JzMakeDescriptor (
+ PCM_PARTIAL_RESOURCE_LIST Descriptor,
+ BOOLEAN Port,
+ ULONG PortStart,
+ ULONG PortSize,
+ BOOLEAN Interrupt,
+ USHORT InterruptFlags,
+ ULONG Level,
+ ULONG Vector,
+ BOOLEAN Memory,
+ ULONG MemoryStart,
+ ULONG MemorySize,
+ BOOLEAN Dma,
+ ULONG Channel,
+ BOOLEAN SecondChannel, // Hack for sound
+ BOOLEAN DeviceSpecificData,
+ ULONG Size,
+ PVOID Data
+ )
+
+/*++
+
+Routine Description:
+
+ This routine creates a resource descriptor structure.
+
+Arguments:
+
+
+Return Value:
+
+ Returns the size of the structure.
+
+--*/
+{
+ ULONG Index;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Partial;
+
+ Index = 0;
+
+ if (Port) {
+ Partial = &Descriptor->PartialDescriptors[Index];
+ Partial->Type = CmResourceTypePort;
+ Partial->ShareDisposition = CmResourceShareDeviceExclusive;
+ Partial->Flags = CM_RESOURCE_PORT_IO;
+ Partial->u.Port.Start.LowPart = PortStart;
+ Partial->u.Port.Start.HighPart = 0;
+ Partial->u.Port.Length = PortSize;
+ Index++;
+ }
+
+ if (Interrupt) {
+ Partial = &Descriptor->PartialDescriptors[Index];
+ Partial->Type = CmResourceTypeInterrupt;
+ Partial->ShareDisposition = CmResourceShareDeviceExclusive;
+ Partial->Flags = InterruptFlags;
+ Partial->u.Interrupt.Level = Level;
+ Partial->u.Interrupt.Vector = Vector;
+ Partial->u.Interrupt.Affinity = 0;
+ Index++;
+ }
+
+ if (Memory) {
+ Partial = &Descriptor->PartialDescriptors[Index];
+ Partial->Type = CmResourceTypeMemory;
+ Partial->ShareDisposition = CmResourceShareDeviceExclusive;
+ Partial->Flags = 0;
+ Partial->u.Memory.Start.LowPart = MemoryStart;
+ Partial->u.Memory.Start.HighPart = 0;
+ Partial->u.Memory.Length = MemorySize;
+ Index++;
+ }
+
+ if (Dma) {
+ Partial = &Descriptor->PartialDescriptors[Index];
+ Partial->Type = CmResourceTypeDma;
+ Partial->ShareDisposition = CmResourceShareDeviceExclusive;
+ Partial->Flags = 0;
+ Partial->u.Dma.Channel = Channel;
+ Partial->u.Dma.Port = 0;
+ Partial->u.Dma.Reserved1 = 0;
+ Index++;
+ if (SecondChannel) {
+ Partial = &Descriptor->PartialDescriptors[Index];
+ Partial->Type = CmResourceTypeDma;
+ Partial->ShareDisposition = CmResourceShareDeviceExclusive;
+ Partial->Flags = 0;
+ Partial->u.Dma.Channel = Channel + 1;
+ Partial->u.Dma.Port = 0;
+ Partial->u.Dma.Reserved1 = 0;
+ Index++;
+ }
+ }
+
+ if (DeviceSpecificData) {
+ // Should add a check for maximum size of data.
+ Partial = &Descriptor->PartialDescriptors[Index];
+ Partial->Type = CmResourceTypeDeviceSpecific;
+ Partial->ShareDisposition = CmResourceShareDeviceExclusive;
+ Partial->Flags = 0;
+ Partial->u.DeviceSpecificData.DataSize = Size;
+ Partial->u.DeviceSpecificData.Reserved1 = 0;
+ Partial->u.DeviceSpecificData.Reserved2 = 0;
+ Index++;
+ RtlMoveMemory((PVOID)&Descriptor->PartialDescriptors[Index], Data, Size);
+ }
+
+ Descriptor->Count = Index;
+ Descriptor->Version = ARC_VERSION;
+ Descriptor->Revision = ARC_REVISION;
+ return(sizeof(CM_PARTIAL_RESOURCE_LIST) +
+ (Index ? ((Index - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)) : 0) +
+ Size);
+
+}
+
+
+VOID
+JzMakeConfiguration (
+ ULONG Monitor,
+ ULONG Floppy,
+ ULONG Floppy2
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the configuration entries by calling the firmware
+ add child routine.
+
+ The addresses stored in the configuration areas are meta-virtual
+ addresses. Reason: keeping within a longword minimizes code changes.
+
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ CONFIGURATION_COMPONENT Component;
+ PCHAR Identifier;
+ PCONFIGURATION_COMPONENT Root, ProcessorLevel, LocalBusLevel,
+ GraphicsBoardLevel, FloppyControllerLevel,
+ KeyboardControllerLevel, MouseControllerLevel,
+ EISAAdapterLevel, MonitorLevel;
+ UCHAR Buffer[sizeof(CM_PARTIAL_RESOURCE_LIST) +
+ (sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * 5) +
+ MAXIMUM_DEVICE_SPECIFIC_DATA];
+ PCM_PARTIAL_RESOURCE_LIST Descriptor = (PCM_PARTIAL_RESOURCE_LIST)&Buffer;
+ ULONG DescriptorSize;
+ //
+ // This is a static in the Alpha sources
+ //
+ // JAZZ_VIDEO_TYPE VideoType;
+ CM_VIDEO_DEVICE_DATA VideoDeviceData;
+ MONITOR_CONFIGURATION_DATA MonitorData; // TEMPTEMP
+ JENSEN_CONFIGURATION_DATA VideoData; // TEMPTEMP
+ CM_MONITOR_DEVICE_DATA MonitorDeviceData;
+ CM_SCSI_DEVICE_DATA ScsiDeviceData;
+ CM_FLOPPY_DEVICE_DATA FloppyDeviceData;
+ CM_SERIAL_DEVICE_DATA SerialDeviceData;
+ ULONG DcacheLineSize, DcacheSize, IcacheLineSize, IcacheSize;
+ ULONG ScacheLineSize, ScacheSize;
+ ULONG Temp;
+ UCHAR VideoIdentifier[32];
+ UCHAR TempString[20];
+ EISA_ADAPTER_DETAILS EisaAdapterDetails;
+ EXTENDED_SYSTEM_INFORMATION SystemInfo;
+
+ SetupROMPendingModified = TRUE;
+
+ //
+ // Add root.
+ //
+
+ VenReturnExtendedSystemInformation(&SystemInfo);
+
+ // Make the string DEC-<system revision #><system variant #><system>
+ sprintf(TempString, "DEC-%d0Jensen", SystemInfo.SystemRevision);
+
+ JzMakeComponent(&Component,
+ SystemClass, // Class
+ ArcSystem, // Type
+ FALSE, // Readonly
+ FALSE, // Removeable
+ FALSE, // ConsoleIn
+ FALSE, // ConsoleOut
+ FALSE, // Input
+ FALSE, // Output
+ 0, // Key
+ 0, // ConfigurationDataLength
+ TempString // Identifier
+ );
+
+ Root = ArcAddChild( NULL, &Component, NULL );
+
+ //
+ // Add processor as child of root.
+ //
+
+ // Make the string DEC-<processor revision><processor type>
+ sprintf(TempString, "DEC-%d%d", SystemInfo.ProcessorRevision,
+ SystemInfo.ProcessorId);
+
+ JzMakeComponent(&Component,
+ ProcessorClass, // Class
+ CentralProcessor, // Type
+ FALSE, // Readonly
+ FALSE, // Removeable
+ FALSE, // ConsoleIn
+ FALSE, // ConsoleOut
+ FALSE, // Input
+ FALSE, // Output
+ 0, // Key
+ 0, // ConfigurationDataLength
+ TempString // Identifier
+ );
+
+ ProcessorLevel = ArcAddChild( Root, &Component, NULL );
+
+ //
+ // Add caches as child of processor.
+ //
+
+ //
+ // Cache parameters are hardcoded for now. They should be
+ // changed into something smarter in the future.
+ //
+
+
+ JzMakeComponent(&Component,
+ CacheClass, // Class
+ PrimaryIcache, // Type
+ FALSE, // Readonly
+ FALSE, // Removeable
+ FALSE, // ConsoleIn
+ FALSE, // ConsoleOut
+ FALSE, // Input
+ FALSE, // Output
+ 0x01050000, // Key: 1 line/block, 32 bytes/line,
+ // 8KB
+ 0, // ConfigurationDataLength
+ NULL // Identifier
+ );
+
+ ArcAddChild( ProcessorLevel, &Component, NULL );
+
+ JzMakeComponent(&Component,
+ CacheClass, // Class
+ PrimaryDcache, // Type
+ FALSE, // Readonly
+ FALSE, // Removeable
+ FALSE, // ConsoleIn
+ FALSE, // ConsoleOut
+ FALSE, // Input
+ FALSE, // Output
+ 0x01050000, // Key: 1 line/block, 32 bytes/line,
+ // 8KB
+ 0, // ConfigurationDataLength
+ NULL // Identifier
+ );
+
+ ArcAddChild( ProcessorLevel, &Component, NULL );
+
+
+ //
+ // Add a secondary cache.
+ //
+
+ JzMakeComponent(&Component,
+ CacheClass, // Class
+ SecondaryCache, // Type
+ FALSE, // Readonly
+ FALSE, // Removeable
+ FALSE, // ConsoleIn
+ FALSE, // ConsoleOut
+ FALSE, // Input
+ FALSE, // Output
+ 0x01050006, // Key: 1 line/block, 32 bytes/line,
+ // 512KB
+ 0, // ConfigurationDataLength
+ NULL // Identifier
+ );
+
+ ArcAddChild( ProcessorLevel, &Component, NULL );
+
+
+ //
+ // Add main memory as a child of the root.
+ //
+
+ JzMakeComponent(&Component,
+ MemoryClass, // Class
+ SystemMemory, // Type
+ FALSE, // Readonly
+ FALSE, // Removeable
+ FALSE, // ConsoleIn
+ FALSE, // ConsoleOut
+ FALSE, // Input
+ FALSE, // Output
+ 0, // Key
+ 0, // ConfigurationDataLength
+ NULL // Identifier
+ );
+
+ ArcAddChild( Root, &Component, NULL );
+
+ //
+ // Add the local bus (HBUS / LBUS) as a child of root.
+ //
+
+ JzMakeComponent(&Component,
+ AdapterClass, // Class
+ MultiFunctionAdapter, // Type
+ FALSE, // Readonly
+ FALSE, // Removeable
+ FALSE, // ConsoleIn
+ FALSE, // ConsoleOut
+ FALSE, // Input
+ FALSE, // Output
+ 0, // Key
+ 0, // ConfigurationDataLength
+ "Jazz-Internal Bus" // Identifier
+ );
+
+ LocalBusLevel = ArcAddChild( Root, &Component, NULL );
+
+
+ //
+ // Add the eisa adapter as a child of root.
+ //
+
+ EisaAdapterDetails.NumberOfSlots = VIR_0_SLOTS ? VIR_0_SLOTS + 16 : PHYS_0_SLOTS;
+ EisaAdapterDetails.IoStart = (PVOID)EISA_EXTERNAL_IO_VIRTUAL_BASE;
+ EisaAdapterDetails.IoSize = PHYS_0_SLOTS * 0x1000;
+
+ EisaAdapterDetails.ConfigDataHeader.Version = ARC_VERSION;
+ EisaAdapterDetails.ConfigDataHeader.Revision = ARC_REVISION;
+ EisaAdapterDetails.ConfigDataHeader.Type = NULL;
+ EisaAdapterDetails.ConfigDataHeader.Vendor = NULL;
+ EisaAdapterDetails.ConfigDataHeader.ProductName = NULL;
+ EisaAdapterDetails.ConfigDataHeader.SerialNumber = NULL;
+
+ JzMakeComponent(&Component,
+ AdapterClass, // Class
+ EisaAdapter, // Type
+ FALSE, // Readonly
+ FALSE, // Removeable
+ FALSE, // ConsoleIn
+ FALSE, // ConsoleOut
+ FALSE, // Input
+ FALSE, // Output
+ 0, // Key
+ sizeof(EISA_ADAPTER_DETAILS), // ConfigurationDataLength
+ "EISA" // Identifier
+ );
+
+ EISAAdapterLevel = ArcAddChild( Root, &Component, &EisaAdapterDetails );
+
+
+
+ //
+ // The SCSI adapter node is needed for both non-ECU and ECU-supporting
+ // firmware packages. The ECU will store per-slot EISA information
+ // under the EISA node. This node represents the booting phantom
+ // node that the rest of the firmware and OSloader uses to touch
+ // bootable disks.
+ //
+ // In an ECU-supporting firmware, any children of this node are actually
+ // children of the first Adaptec board (i.e., the one in the lowest-
+ // numbered EISA slot).
+ //
+
+ ScsiDeviceData.Version = ARC_VERSION;
+ ScsiDeviceData.Revision = ARC_REVISION;
+ ScsiDeviceData.HostIdentifier = ScsiHostId;
+
+ DescriptorSize =
+ JzMakeDescriptor (Descriptor, // Descriptor
+ FALSE, // Port
+ 0, // PortStart
+ 0, // PortSize
+ TRUE, // Interrupt
+ 0, // InterruptFlags
+ EISA_DEVICE_LEVEL, // Level
+ 0, // Vector
+ FALSE, // Memory
+ 0, // MemoryStart
+ 0, // MemorySize
+ TRUE, // Dma
+ SCSI_CHANNEL, // Channel
+ FALSE, // SecondChannel
+ TRUE, // DeviceSpecificData
+ sizeof(CM_SCSI_DEVICE_DATA), // Size
+ (PVOID)&ScsiDeviceData // Data
+ );
+
+ JzMakeComponent(&Component,
+ AdapterClass, // Class
+ ScsiAdapter, // Type
+ FALSE, // Readonly
+ FALSE, // Removeable
+ FALSE, // ConsoleIn
+ FALSE, // ConsoleOut
+ FALSE, // Input
+ FALSE, // Output
+ 0, // Key
+ DescriptorSize, // ConfigurationDataLength
+ "AHA1742" // Identifier
+ );
+
+ ArcAddChild( Root, &Component, Descriptor );
+
+ //
+ // Add in a number of predefined nodes off the EISA component
+ // if this is *not* a build for an ECU-supported machine.
+ //
+
+
+#ifndef ALPHA_FW_ECU
+
+ //
+ // Add graphics board as a child of the EISA bus.
+ //
+
+ VideoData.Irql = ISA_DEVICE_LEVEL;
+ VideoData.Vector = 0;
+ VideoData.Version = 1;
+ VideoData.Revision = 0;
+ VideoData.ControlBase = VIDEO_CONTROL_VIRTUAL_BASE;
+ VideoData.ControlSize = PAGE_SIZE << 9;
+// VideoData.CursorBase = CURSOR_CONTROL_PHYSICAL_BASE;
+// VideoData.CursorSize = PAGE_SIZE;
+ VideoData.CursorBase = 0;
+ VideoData.CursorSize = 0;
+ VideoData.FrameBase = VIDEO_MEMORY_VIRTUAL_BASE;
+ VideoData.FrameSize = PAGE_SIZE << 9;
+
+ //
+ // Plug in the video board type
+ //
+
+ switch (VideoType) {
+
+ case _Paradise_WD90C11:
+ Identifier = "Paradise WD90C11";
+ break;
+
+ case _Compaq_QVision:
+
+ Identifier = "Compaq QVision";
+ break;
+
+ case _Cardinal_S3_924:
+ Identifier = "Cardinal S3 911/924";
+ break;
+
+ case _S3_928:
+ Identifier = "S3 928";
+ break;
+
+ case _ATI_Mach:
+ Identifier = "ATI Mach";
+ break;
+
+ default:
+ Identifier = "Unknown";
+ break;
+ }
+
+ JzMakeComponent(&Component,
+ ControllerClass, // Class
+ DisplayController, // Type
+ FALSE, // Readonly
+ FALSE, // Removeable
+ FALSE, // ConsoleIn
+ TRUE, // ConsoleOut
+ FALSE, // Input
+ TRUE, // Output
+ 0, // Key
+ sizeof(JENSEN_CONFIGURATION_DATA), // ConfigurationDataLength
+ Identifier // Identifier
+ );
+
+ GraphicsBoardLevel = ArcAddChild( EISAAdapterLevel, &Component, &VideoData );
+
+ //
+ // Add the monitor as a child of the graphics board.
+ //
+
+ JzMakeComponent(&Component,
+ PeripheralClass, // Class
+ MonitorPeripheral, // Type
+ FALSE, // Readonly
+ FALSE, // Removeable
+ FALSE, // ConsoleIn
+ TRUE, // ConsoleOut
+ FALSE, // Input
+ TRUE, // Output
+ 0, // Key
+ sizeof(MONITOR_CONFIGURATION_DATA), // ConfigurationDataLength
+ NULL // Identifier
+ );
+
+ MonitorData.Version = 1;
+ MonitorData.Revision = 0;
+
+ switch (Monitor) {
+
+ case 0:
+ Component.IdentifierLength = sizeof("1280x1024");
+ Component.Identifier = "1280x1024";
+
+#if 0
+// Jazz code
+ MonitorData.HorizontalResolution = 1280;
+ MonitorData.HorizontalDisplayTime = 11832; // Mips uses 11636
+// MonitorData.HorizontalBackPorch = 1746;
+// MonitorData.HorizontalFrontPorch = 437;
+ MonitorData.HorizontalBackPorch = 1596; // Mips uses 2070
+ MonitorData.HorizontalFrontPorch = 587; // Mips uses 407
+ MonitorData.HorizontalSync = 1745; // Mips uses 1701
+ MonitorData.VerticalResolution = 1024;
+ MonitorData.VerticalBackPorch = 28; // Mips uses 32
+ MonitorData.VerticalFrontPorch = 1;
+ MonitorData.VerticalSync = 3;
+ MonitorData.HorizontalScreenSize = 343;
+ MonitorData.VerticalScreenSize = 274;
+#else
+// Jensen code
+ MonitorData.HorizontalResolution = 1280;
+ MonitorData.HorizontalDisplayTime = 0;
+ MonitorData.HorizontalBackPorch = 0;
+ MonitorData.HorizontalFrontPorch = 0;
+ MonitorData.HorizontalSync = 0;
+ MonitorData.VerticalResolution = 1024;
+ MonitorData.VerticalBackPorch = 0;
+ MonitorData.VerticalFrontPorch = 0;
+ MonitorData.VerticalSync = 0;
+ MonitorData.HorizontalScreenSize = 0;
+ MonitorData.VerticalScreenSize = 0;
+#endif
+
+ break;
+
+ case 1:
+ Component.IdentifierLength = sizeof("1024x768");
+ Component.Identifier = "1024x768";
+
+#if 0
+// Jazz code.
+ MonitorData.HorizontalResolution = 1024;
+ MonitorData.HorizontalDisplayTime = 16000; // Mips uses 15754
+ MonitorData.HorizontalBackPorch = 2000; // Mips uses 2462
+ MonitorData.HorizontalFrontPorch = 1000; // Mips uses 369
+ MonitorData.HorizontalSync = 1500; // Mips uses 2092
+ MonitorData.VerticalResolution = 768;
+ MonitorData.VerticalBackPorch = 39; // Mips uses 35
+ MonitorData.VerticalFrontPorch = 1;
+ MonitorData.VerticalSync = 1; // Mips uses 3
+ MonitorData.HorizontalScreenSize = 343;
+ MonitorData.VerticalScreenSize = 274;
+#else
+// Jensen code
+ MonitorData.HorizontalResolution = 1024;
+ MonitorData.HorizontalDisplayTime = 0;
+ MonitorData.HorizontalBackPorch = 0;
+ MonitorData.HorizontalFrontPorch = 0;
+ MonitorData.HorizontalSync = 0;
+ MonitorData.VerticalResolution = 768;
+ MonitorData.VerticalBackPorch = 0;
+ MonitorData.VerticalFrontPorch = 0;
+ MonitorData.VerticalSync = 0;
+ MonitorData.HorizontalScreenSize = 0;
+ MonitorData.VerticalScreenSize = 0;
+#endif
+
+ break;
+
+ case 2:
+ Component.IdentifierLength = sizeof("800x600");
+ Component.Identifier = "800x600";
+
+#if 0
+// Jazz code.
+ MonitorData.HorizontalResolution = 800;
+ MonitorData.HorizontalDisplayTime = 14130;
+ MonitorData.HorizontalBackPorch = 2670;
+ MonitorData.HorizontalFrontPorch = 440;
+ MonitorData.HorizontalSync = 3110;
+ MonitorData.VerticalResolution = 600;
+// MonitorData.VerticalBackPorch = 7;
+ MonitorData.VerticalBackPorch = 18;
+ MonitorData.VerticalFrontPorch = 1;
+// MonitorData.VerticalSync = 14;
+ MonitorData.VerticalSync = 3;
+ MonitorData.HorizontalScreenSize = 343;
+ MonitorData.VerticalScreenSize = 274;
+#else
+// Jensen code.
+ MonitorData.HorizontalResolution = 800;
+ MonitorData.HorizontalDisplayTime = 0;
+ MonitorData.HorizontalBackPorch = 0;
+ MonitorData.HorizontalFrontPorch = 0;
+ MonitorData.HorizontalSync = 0;
+ MonitorData.VerticalResolution = 600;
+ MonitorData.VerticalBackPorch = 0;
+ MonitorData.VerticalFrontPorch = 0;
+ MonitorData.VerticalSync = 0;
+ MonitorData.HorizontalScreenSize = 0;
+ MonitorData.VerticalScreenSize = 0;
+#endif
+
+ break;
+
+ case 3:
+ Component.IdentifierLength = sizeof("640x480");
+ Component.Identifier = "640x480";
+
+#if 0
+// Jazz code.
+ MonitorData.HorizontalResolution = 640;
+ MonitorData.HorizontalDisplayTime = 25422;
+ MonitorData.HorizontalBackPorch = 1907;
+ MonitorData.HorizontalFrontPorch = 636;
+ MonitorData.HorizontalSync = 3814;
+ MonitorData.VerticalResolution = 480;
+ MonitorData.VerticalBackPorch = 33;
+ MonitorData.VerticalFrontPorch = 10;
+ MonitorData.VerticalSync = 2;
+ MonitorData.HorizontalScreenSize = 350;
+ MonitorData.VerticalScreenSize = 270;
+
+#else
+// Jensen code.
+
+ MonitorData.HorizontalResolution = 640;
+ MonitorData.HorizontalDisplayTime = 0;
+ MonitorData.HorizontalBackPorch = 0;
+ MonitorData.HorizontalFrontPorch = 0;
+ MonitorData.HorizontalSync = 0;
+ MonitorData.VerticalResolution = 480;
+ MonitorData.VerticalBackPorch = 0;
+ MonitorData.VerticalFrontPorch = 0;
+ MonitorData.VerticalSync = 0;
+ MonitorData.HorizontalScreenSize = 0;
+ MonitorData.VerticalScreenSize = 0;
+#endif
+
+ break;
+
+ default:
+ break;
+
+ }
+
+ MonitorLevel = ArcAddChild( GraphicsBoardLevel, &Component, &MonitorData );
+
+#endif // ALPHA_FW_ECU
+
+
+ //
+ // Add the floppy disk controller as a child of the EISA Adapter.
+ //
+ // Because of the way the EISA Configuration Utility works, this is
+ // no longer done here. Environement variables are used to transfer
+ // the floppy configuration information to code in the jxboot.c module.
+ //
+
+ switch (Floppy) {
+
+ case 0:
+ Identifier = "0";
+ break;
+
+ case 1:
+ Identifier = "1";
+ break;
+
+ case 2:
+ default:
+ Identifier = "2";
+ break;
+ }
+
+ FwCoreSetEnvironmentVariable("FLOPPY", Identifier, FALSE);
+
+ switch (Floppy2) {
+
+ case -1:
+ Identifier = "N";
+ break;
+
+ case 0:
+ Identifier = "0";
+ break;
+
+ case 1:
+ Identifier = "1";
+ break;
+
+ case 2:
+ default:
+ Identifier = "2";
+ break;
+ }
+
+ FwCoreSetEnvironmentVariable("FLOPPY2", Identifier, FALSE);
+
+ //
+ // Add the keyboard controller as a child of the local bus.
+ //
+ // Jensen wants the Portstart to be the ISA port address of the
+ // controller in the 82C106 combo chip.
+ //
+
+ DescriptorSize =
+ JzMakeDescriptor (Descriptor, // Descriptor
+ TRUE, // Port
+ KEYBOARD_ISA_PORT_ADDRESS, // PortStart
+ 8, // PortSize
+ TRUE, // Interrupt
+ 0, // InterruptFlags
+ EISA_DEVICE_LEVEL, // Level
+ KEYBOARD_MOUSE_VECTOR, // Vector
+ FALSE, // Memory
+ 0, // MemoryStart
+ 0, // MemorySize
+ FALSE, // Dma
+ 0, // Channel
+ FALSE, // SecondChannel
+ FALSE, // DeviceSpecificData
+ 0, // Size
+ NULL // Data
+ );
+
+ JzMakeComponent(&Component,
+ ControllerClass, // Class
+ KeyboardController, // Type
+ FALSE, // Readonly
+ FALSE, // Removeable
+ TRUE, // ConsoleIn
+ FALSE, // ConsoleOut
+ TRUE, // Input
+ FALSE, // Output
+ 0, // Key
+ DescriptorSize, // ConfigurationDataLength
+ NULL // Identifier
+ );
+
+ KeyboardControllerLevel = ArcAddChild( LocalBusLevel, &Component, Descriptor );
+
+ //
+ // Add the keyboard itself as a child of the keyboard controller.
+ //
+
+ JzMakeComponent(&Component,
+ PeripheralClass, // Class
+ KeyboardPeripheral, // Type
+ FALSE, // Readonly
+ FALSE, // Removeable
+ TRUE, // ConsoleIn
+ FALSE, // ConsoleOut
+ TRUE, // Input
+ FALSE, // Output
+ 0, // Key
+ 0, // ConfigurationDataLength
+ "101-KEY" // Identifier
+ );
+
+ ArcAddChild(KeyboardControllerLevel, &Component, NULL);
+
+
+ //
+ // Add the mouse controller as a child of the local bus.
+ //
+ // Jensen wants the Portstart to be the ISA port address of the
+ // controller in the 82C106 combo chip.
+ //
+
+ DescriptorSize =
+ JzMakeDescriptor (Descriptor, // Descriptor
+ TRUE, // Port
+ MOUSE_ISA_PORT_ADDRESS, // PortStart
+ 8, // PortSize
+ TRUE, // Interrupt
+ 0, // InterruptFlags
+ EISA_DEVICE_LEVEL, // Level
+ KEYBOARD_MOUSE_VECTOR, // Vector
+ FALSE, // Memory
+ 0, // MemoryStart
+ 0, // MemorySize
+ FALSE, // Dma
+ 0, // Channel
+ FALSE, // SecondChannel
+ FALSE, // DeviceSpecificData
+ 0, // Size
+ NULL // Data
+ );
+
+ JzMakeComponent(&Component,
+ ControllerClass, // Class
+ PointerController, // Type
+ FALSE, // Readonly
+ FALSE, // Removeable
+ FALSE, // ConsoleIn
+ FALSE, // ConsoleOut
+ TRUE, // Input
+ FALSE, // Output
+ 0, // Key
+ DescriptorSize, // ConfigurationDataLength
+ NULL // Identifier
+ );
+
+ MouseControllerLevel = ArcAddChild( LocalBusLevel, &Component, Descriptor );
+
+ //
+ // Add the mouse itself as a child of the mouse controller.
+ //
+
+ JzMakeComponent(&Component,
+ PeripheralClass, // Class
+ PointerPeripheral, // Type
+ FALSE, // Readonly
+ FALSE, // Removeable
+ FALSE, // ConsoleIn
+ FALSE, // ConsoleOut
+ TRUE, // Input
+ FALSE, // Output
+ 0, // Key
+ 0, // ConfigurationDataLength
+ "PS2 MOUSE" // Identifier
+ );
+
+ ArcAddChild( MouseControllerLevel, &Component, NULL );
+
+ //
+ // Add the serial and parallel controllers as children of the
+ // local bus.
+ //
+ // Jensen wants the Portstart to be the ISA port address of the
+ // controller in the 82C106 combo chip.
+ //
+
+ // Alpha/Jensen: set the baud clock field to 1.8432 MHz.
+
+ SerialDeviceData.BaudClock = 1843200;
+
+
+ SerialDeviceData.Version = ARC_VERSION;
+ SerialDeviceData.Revision = ARC_REVISION;
+
+ DescriptorSize =
+ JzMakeDescriptor (Descriptor, // Descriptor
+ TRUE, // Port
+ SP0_ISA_PORT_ADDRESS, // PortStart
+ 8, // PortSize
+ TRUE, // Interrupt
+ 0, // InterruptFlags
+ EISA_DEVICE_LEVEL, // Level
+ SERIAL_VECTOR, // Vector
+ FALSE, // Memory
+ 0, // MemoryStart
+ 0, // MemorySize
+ FALSE, // Dma
+ 0, // Channel
+ FALSE, // SecondChannel
+ TRUE, // DeviceSpecificData
+ sizeof(CM_SERIAL_DEVICE_DATA), // Size
+ (PVOID)&SerialDeviceData // Data
+ );
+
+ JzMakeComponent(&Component,
+ ControllerClass, // Class
+ SerialController, // Type
+ FALSE, // Readonly
+ FALSE, // Removeable
+ FALSE, // ConsoleIn
+ FALSE, // ConsoleOut
+ TRUE, // Input
+ TRUE, // Output
+ 0, // Key
+ DescriptorSize, // ConfigurationDataLength
+ "COM1" // Identifier
+ );
+
+ ArcAddChild( LocalBusLevel, &Component, Descriptor );
+
+ DescriptorSize =
+ JzMakeDescriptor (Descriptor, // Descriptor
+ TRUE, // Port
+ SP1_ISA_PORT_ADDRESS, // PortStart
+ 8, // PortSize
+ TRUE, // Interrupt
+ 0, // InterruptFlags
+ EISA_DEVICE_LEVEL, // Level
+ SERIAL_VECTOR, // Vector
+ FALSE, // Memory
+ 0, // MemoryStart
+ 0, // MemorySize
+ FALSE, // Dma
+ 0, // Channel
+ FALSE, // SecondChannel
+ TRUE, // DeviceSpecificData
+ sizeof(CM_SERIAL_DEVICE_DATA), // Size
+ (PVOID)&SerialDeviceData // Data
+ );
+
+ JzMakeComponent(&Component,
+ ControllerClass, // Class
+ SerialController, // Type
+ FALSE, // Readonly
+ FALSE, // Removeable
+ FALSE, // ConsoleIn
+ FALSE, // ConsoleOut
+ TRUE, // Input
+ TRUE, // Output
+ 0, // Key
+ DescriptorSize, // ConfigurationDataLength
+ "COM2" // Identifier
+ );
+
+ ArcAddChild( LocalBusLevel, &Component, Descriptor );
+
+ DescriptorSize =
+ JzMakeDescriptor (Descriptor, // Descriptor
+ TRUE, // Port
+ PARALLEL_ISA_PORT_ADDRESS, // PortStart
+ 8, // PortSize
+ TRUE, // Interrupt
+ CM_RESOURCE_INTERRUPT_LATCHED, // InterruptFlags
+ EISA_DEVICE_LEVEL, // Level
+ PARALLEL_VECTOR, // Vector
+ FALSE, // Memory
+ 0, // MemoryStart
+ 0, // MemorySize
+ FALSE, // Dma
+ 0, // Channel
+ FALSE, // SecondChannel
+ FALSE, // DeviceSpecificData
+ 0, // Size
+ NULL // Data
+ );
+
+ JzMakeComponent(&Component,
+ ControllerClass, // Class
+ ParallelController, // Type
+ FALSE, // Readonly
+ FALSE, // Removeable
+ FALSE, // ConsoleIn
+ FALSE, // ConsoleOut
+ TRUE, // Input
+ TRUE, // Output
+ 0, // Key
+ DescriptorSize, // ConfigurationDataLength
+ "LPT1" // Identifier
+ );
+
+ ArcAddChild( LocalBusLevel, &Component, Descriptor );
+
+ return;
+}
diff --git a/private/ntos/fw/alpha/jensen/alpha/jxmemory.c b/private/ntos/fw/alpha/jensen/alpha/jxmemory.c
new file mode 100644
index 000000000..913b4feb1
--- /dev/null
+++ b/private/ntos/fw/alpha/jensen/alpha/jxmemory.c
@@ -0,0 +1,817 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ jxmemory.c
+
+Abstract:
+
+ This module implements the ARC firmware memory configuration operations
+ for an Alpha/Jensen system.
+
+Author:
+
+ David N. Cutler (davec) 18-May-1991
+
+
+Revision History:
+
+ 26-May-1992 John DeRosa [DEC]
+
+ Added Alpha/Jensen hooks.
+
+--*/
+
+#include "fwp.h"
+#include "fwstring.h"
+
+extern end[];
+
+// Defined in selftest.c
+extern ALPHA_VIDEO_TYPE VideoType;
+
+//
+// Define memory listhead, allocation entries, and free index.
+//
+
+ULONG FwMemoryFree;
+LIST_ENTRY FwMemoryListHead;
+FW_MEMORY_DESCRIPTOR FwMemoryTable[FW_MEMORY_TABLE_SIZE];
+
+
+//
+// This is used to remember EISA memory buffers that must be marked
+// as bad each time the memory descriptors are initialized.
+//
+
+typedef struct _EISA_BUFFER_ENTRY {
+ ULONG PageAddress;
+ ULONG PageCount;
+} EISA_BUFFER_ENTRY, *PEISA_BUFFER_ENTRY;
+
+EISA_BUFFER_ENTRY EISABuffersToBeMarked[FW_MEMORY_TABLE_SIZE];
+
+ULONG EISABufferListPointer;
+
+
+
+//
+// Local function prototypes
+//
+
+ARC_STATUS
+EisaMarkBadMemory (
+ VOID
+ );
+
+
+VOID
+FwInitializeMemory (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the memory allocation list for the memory
+ configuration routine.
+
+ Note that the BasePage addresses are not in super-page mode.
+
+ The boot memory layout of Jensen is as follows. The rightmost
+ column lists how this function defines each region.
+
+
+ base distance what memory descriptor region
+ address from 0 at boot time (after
+ FwInitializeMemory)
+ ------- -------- ----- --------------------------
+
+ 0 0 unused MemoryFree
+
+ 80000 .5 MB kernel, MemoryFree
+ loaded progs
+
+ 400000 4 MB HAL MemoryFree
+
+ 600000 6 MB OSloader MemoryFree
+
+ 6FE000 7 MB System Param MemoryFirmwarePermanent
+ -8KB Block, assoc.
+ vectors,
+ Restart Block
+
+ 700000 7 MB FW PAL MemoryFirmwarePermanent
+
+ 704000 7 MB FW code, MemoryFirmwarePermanent
+ +16KB FW data
+
+ 750000 7 MB Panic stack MemoryFirmwarePermanent
+ +328KB area
+
+ 760000 7.5 MB FW stack MemoryFirmwarePermanent
+ -128KB (grows from
+ 770000 downward)
+
+ 770000 7.5 MB FW Pool MemoryFirmwareTemporary
+ -64KB (128 KB)
+
+ 790000 7.5 MB unused MemoryFree
+ +64KB ( --> remainder of memory )
+
+
+
+ Notes:
+
+ 1. The page at 0x6fe000 contains:
+
+ . System Parameter Block, with only one Adapter Vector
+ (currently 0x3c bytes)
+ . ARC firmware vector (currently 0x94 bytes)
+ . Vendor vector (currently 0x34 bytes)
+ . EISA adapter vector (currently 0x4c bytes)
+ . Restart block
+ . Alpha restart save area.
+
+ The length of these structures will change if the number of
+ adapters, vendor functions, ARC firmware functions, etc. changes.
+
+ Currently:
+
+ SPB+FV+VV+EAV = 336 bytes
+ RB = 80 bytes
+ ARSA = 2000 bytes
+ ====
+ ~2.4KB total
+
+
+ 2. Theta debug note: The Theta mini-console lives between
+ 0 and 40000. It is reloaded from ROM on a halt-button or power-up,
+ but *not* on a Halt instruction or exception. I therefore mark
+ this region as MemoryFirmwarePermanent. The Jensen product will
+ mark this region as MemoryFree, as per the chart.
+
+
+ 3. Firmware PALcode must be aligned on a 16KB boundary.
+
+
+ 4. Memory descriptor initialization assumes that certain critical
+ numbers are even multiples of EV4 pages (8KB). The #defines are in
+ \nt\private\ntos\fw\alpha\fwp.h. "ROUND" macros could be used to
+ calculate page multiples on the fly, but are not yet.
+
+
+ 5. On Jensen, EISA DMA addresses overlap with Jensen memory space,
+ and so a DMA from board X can erroneously write into the framebuffer
+ for board Y. (E.g.: an Adaptec disk card and a Compaq QVision board.)
+
+ The solution chosen for Jensen is to mark EISA memory buffer addresses
+ as "Bad" memory, so NT will not try to use those locations for anything
+ interesting.
+
+ There are two solutions:
+
+ . hack: Mark the 32nd MB of memory as bad for QVision board debug.
+
+ This is on Firmware versions <= 1.06.
+
+ . real solution: The ECU determines where the buffer goes, and the
+ Firmware reads the EISA configuration information to set the
+ buffer addresses for any memory-buffer'd board to "Bad". In reality,
+ the 32nd MB of memory will be marked bad for QVision, but this
+ becomes hardwired in the Jensen QVision .CFG file and not in
+ the firmware.
+
+ This may be enabled as early as Firmware version 1.07.
+
+
+Arguments:
+
+ None.
+
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ARC_STATUS Status;
+ ULONG MemoryPages;
+
+ //
+ // Initialize the memory allocation listhead.
+ //
+
+ InitializeListHead(&FwMemoryListHead);
+
+
+ //
+ // Initialize the entry for the free area below the firmware.
+ //
+
+ FwMemoryTable[0].MemoryEntry.MemoryType = MemoryFree;
+ FwMemoryTable[0].MemoryEntry.BasePage = 0;
+ FwMemoryTable[0].MemoryEntry.PageCount =
+ FW_BOTTOM_ADDRESS >> PAGE_SHIFT;
+ InsertTailList(&FwMemoryListHead, &FwMemoryTable[0].ListEntry);
+
+
+ //
+ // Initialize the entry for the firmware SYSTEM_BLOCK, PALcode, code,
+ // data, and stack.
+ //
+
+ FwMemoryTable[1].MemoryEntry.MemoryType = MemoryFirmwarePermanent;
+ FwMemoryTable[1].MemoryEntry.BasePage = FW_BOTTOM_ADDRESS >> PAGE_SHIFT;
+ FwMemoryTable[1].MemoryEntry.PageCount = FW_PAGES;
+ InsertTailList(&FwMemoryListHead, &FwMemoryTable[1].ListEntry);
+
+
+ //
+ // Initialize the entry for the firmware pool.
+ //
+
+ FwMemoryTable[2].MemoryEntry.MemoryType = MemoryFirmwareTemporary;
+ FwMemoryTable[2].MemoryEntry.BasePage = FW_POOL_BASE >> PAGE_SHIFT;
+ FwMemoryTable[2].MemoryEntry.PageCount = FW_POOL_SIZE >> PAGE_SHIFT;
+ InsertTailList(&FwMemoryListHead, &FwMemoryTable[2].ListEntry);
+
+
+ //
+ // Initialize the entry for the rest of memory.
+ //
+
+ MemoryPages = MemorySize >> PAGE_SHIFT;
+
+ FwMemoryTable[3].MemoryEntry.MemoryType = MemoryFree;
+ FwMemoryTable[3].MemoryEntry.BasePage =
+ FW_BASE_REMAINDER_MEMORY >> PAGE_SHIFT;
+ FwMemoryTable[3].MemoryEntry.PageCount =
+ MemoryPages - (FW_BASE_REMAINDER_MEMORY >> PAGE_SHIFT);
+ InsertTailList(&FwMemoryListHead, &FwMemoryTable[3].ListEntry);
+
+
+#ifdef ISA_PLATFORM
+
+ //
+ // Code compiled in if this is not a build for an ECU-ized firmware.
+ //
+
+ //
+ // Jensen QVision hack
+ //
+
+ if (VideoType == _Compaq_QVision) {
+
+ //
+ // A Compaq QVision video board is in the system. Mark the
+ // 32nd megabyte as bad, so that the video boards framebuffer can be
+ // mapped there. This is the megabyte starting at 0x1f00000.
+ //
+
+ ULONG BufferAddress;
+
+ BufferAddress = THIRTY_ONE_MB >> 20;
+
+ if (MemorySize < THIRTY_TWO_MB) {
+
+ //
+ // This system has 31. or less MB of memory. The mapped
+ // Compaq buffer is after the end of real memory.
+ //
+
+ FwMemoryTable[4].MemoryEntry.MemoryType = MemoryBad;
+ FwMemoryTable[4].MemoryEntry.BasePage = THIRTY_ONE_MB >> PAGE_SHIFT;
+ FwMemoryTable[4].MemoryEntry.PageCount = ONE_MB >> PAGE_SHIFT;
+ InsertTailList(&FwMemoryListHead, &FwMemoryTable[4].ListEntry);
+
+ FwMemoryFree = 5;
+
+ } else if (MemorySize == THIRTY_TWO_MB) {
+
+
+ //
+ // This system has 32. MB of memory. The mapped Compaq buffer
+ // is the very last megabyte at the end of memory.
+ //
+
+ // Reduce the memory free area by 1MB
+ FwMemoryTable[3].MemoryEntry.PageCount -= (ONE_MB >> PAGE_SHIFT);
+
+ FwMemoryTable[4].MemoryEntry.MemoryType = MemoryBad;
+ FwMemoryTable[4].MemoryEntry.BasePage = THIRTY_ONE_MB >> PAGE_SHIFT;
+ FwMemoryTable[4].MemoryEntry.PageCount = ONE_MB >> PAGE_SHIFT;
+ InsertTailList(&FwMemoryListHead, &FwMemoryTable[4].ListEntry);
+
+ FwMemoryFree = 5;
+
+ } else {
+
+ //
+ // This system has more than 32MB of memory. The QVision
+ // buffer is wholly within the free memory section at the end
+ // of memory.
+ //
+
+ // Save the number of pages currently in high free memory region
+ MemoryPages = FwMemoryTable[3].MemoryEntry.PageCount;
+
+ // Shunt off the top free page region.
+ FwMemoryTable[3].MemoryEntry.PageCount =
+ (THIRTY_ONE_MB >> PAGE_SHIFT) -
+ FwMemoryTable[3].MemoryEntry.BasePage;
+
+ // Make the entry for the Compaq buffer
+ FwMemoryTable[4].MemoryEntry.MemoryType = MemoryBad;
+ FwMemoryTable[4].MemoryEntry.BasePage = THIRTY_ONE_MB >> PAGE_SHIFT;
+ FwMemoryTable[4].MemoryEntry.PageCount = ONE_MB >> PAGE_SHIFT;
+ InsertTailList(&FwMemoryListHead, &FwMemoryTable[4].ListEntry);
+
+ // Make the entry for the system memory above the Compaq buffer
+ FwMemoryTable[5].MemoryEntry.MemoryType = MemoryFree;
+ FwMemoryTable[5].MemoryEntry.BasePage = THIRTY_TWO_MB >> PAGE_SHIFT;
+
+ //
+ // The pagecount is: (Previous number of pages) -
+ // (Free memory pages below Compaq buffer) -
+ // (Compaq buffer pages)
+ //
+
+ FwMemoryTable[5].MemoryEntry.PageCount =
+ MemoryPages -
+ FwMemoryTable[3].MemoryEntry.PageCount -
+ (ONE_MB >> PAGE_SHIFT);
+
+ InsertTailList(&FwMemoryListHead, &FwMemoryTable[5].ListEntry);
+
+ FwMemoryFree = 6;
+ }
+
+
+ } else {
+
+ // The system video board is not a Compaq QVision.
+
+ FwMemoryFree = 4;
+ }
+
+#else
+
+ //
+ // Code compiled in if this is a build for an ECU-ized firmware.
+ //
+
+ FwMemoryFree = 4;
+
+#endif
+
+
+#if 0
+ //
+ // What Theta should do
+ //
+
+ FwMemoryTable[0].MemoryEntry.MemoryType = MemoryFirmwarePermanent;
+ FwMemoryTable[0].MemoryEntry.PageCount = 0x40000 >> PAGE_SHIFT;
+
+ FwMemoryTable[4].MemoryEntry.MemoryType = MemoryFree;
+ FwMemoryTable[4].MemoryEntry.BasePage = 0x40000 >> PAGE_SHIFT;
+ FwMemoryTable[4].MemoryEntry.PageCount =
+ ((FW_BOTTOM_ADDRESS - 0x40000) >> PAGE_SHIFT);
+ InsertTailList(&FwMemoryListHead, &FwMemoryTable[4].ListEntry);
+
+ FwMemoryFree = 5;
+#endif
+
+
+ //
+ // Initialize the memory configuration routine address in the system
+ // parameter block.
+ //
+
+ (PARC_MEMORY_ROUTINE)SYSTEM_BLOCK->FirmwareVector[MemoryRoutine] =
+ FwGetMemoryDescriptor;
+
+ //
+ // Now mark the necessary EISA buffers as Bad Memory.
+ //
+
+ if ((Status = EisaMarkBadMemory()) != ESUCCESS) {
+ KeBugCheck(Status);
+ } else {
+ return;
+ }
+}
+
+PMEMORY_DESCRIPTOR
+FwGetMemoryDescriptor (
+ IN PMEMORY_DESCRIPTOR MemoryDescriptor OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This routine returns a pointer to the next memory descriptor. If
+ the specified memory descriptor is NULL, then a pointer to the
+ first memory descriptor is returned. If there are no more memory
+ descriptors, then NULL is returned.
+
+Arguments:
+
+ MemoryDescriptor - Supplies a optional pointer to a memory descriptor.
+
+Return Value:
+
+ If there are any more entries in the memory descriptor list, the
+ address of the next descriptor is returned. Otherwise, NULL is
+ returned.
+
+--*/
+
+{
+
+ PFW_MEMORY_DESCRIPTOR TableEntry;
+ PLIST_ENTRY NextEntry;
+
+ //
+ // If a memory descriptor address is specified, then return the
+ // address of the next descriptor or NULL as appropriate. Otherwise,
+ // return the address of the first memory descriptor.
+ //
+
+ if (ARGUMENT_PRESENT(MemoryDescriptor)) {
+ TableEntry = CONTAINING_RECORD(MemoryDescriptor,
+ FW_MEMORY_DESCRIPTOR,
+ MemoryEntry);
+
+ NextEntry = TableEntry->ListEntry.Flink;
+ if (NextEntry != &FwMemoryListHead) {
+ return &(CONTAINING_RECORD(NextEntry,
+ FW_MEMORY_DESCRIPTOR,
+ ListEntry)->MemoryEntry);
+
+ } else {
+ return NULL;
+ }
+
+ } else {
+ return &FwMemoryTable[0].MemoryEntry;
+ }
+}
+
+VOID
+FwGenerateDescriptor (
+ IN PFW_MEMORY_DESCRIPTOR MemoryDescriptor,
+ IN MEMORY_TYPE MemoryType,
+ IN ULONG BasePage,
+ IN ULONG PageCount
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates a new memory descriptor to describe the
+ specified region of memory which is assumed to lie totally within
+ the specified region.
+
+Arguments:
+
+ MemoryDescriptor - Supplies a pointer to a free memory descriptor
+ from which the specified memory is to be allocated.
+
+ MemoryType - Supplies the type that is assigned to the allocated
+ memory.
+
+ BasePage - Supplies the base page number.
+
+ PageCount - Supplies the number of pages.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PLIST_ENTRY NextEntry;
+ ULONG Offset;
+
+ //
+ // If the specified region totally consumes the free region, then no
+ // additional descriptors need to be allocated. If the specified region
+ // is at the start or end of the free region, then only one descriptor
+ // needs to be allocated. Otherwise, two additional descriptors need to
+ // be allocated.
+ //
+
+ Offset = BasePage - MemoryDescriptor->MemoryEntry.BasePage;
+ if ((Offset == 0) && (PageCount == MemoryDescriptor->MemoryEntry.PageCount)) {
+
+ //
+ // The specified region totally consumes the free region.
+ //
+
+ MemoryDescriptor->MemoryEntry.MemoryType = MemoryType;
+
+ } else {
+
+ //
+ // A memory descriptor must be generated to describe the allocated
+ // memory.
+ //
+
+ INCREMENT_FWMEMORYFREE;
+ FwMemoryTable[FwMemoryFree-1].MemoryEntry.MemoryType = MemoryType;
+ FwMemoryTable[FwMemoryFree-1].MemoryEntry.BasePage = BasePage;
+ FwMemoryTable[FwMemoryFree-1].MemoryEntry.PageCount = PageCount;
+ InsertTailList(&FwMemoryListHead,
+ &FwMemoryTable[FwMemoryFree-1].ListEntry);
+
+
+ //
+ // Determine whether an additional memory descriptor must be generated.
+ //
+
+ if (BasePage == MemoryDescriptor->MemoryEntry.BasePage) {
+
+ //
+ // The specified region lies at the start of the free region.
+ //
+
+ MemoryDescriptor->MemoryEntry.BasePage += PageCount;
+ MemoryDescriptor->MemoryEntry.PageCount -= PageCount;
+
+ } else if ((Offset + PageCount) == MemoryDescriptor->MemoryEntry.PageCount) {
+
+ //
+ // The specified region lies at the end of the free region.
+ //
+
+ MemoryDescriptor->MemoryEntry.PageCount -= PageCount;
+
+ } else {
+
+ //
+ // The specified region lies in the middle of the free region.
+ // Another memory descriptor must be generated.
+ //
+
+ INCREMENT_FWMEMORYFREE;
+ FwMemoryTable[FwMemoryFree-1].MemoryEntry.MemoryType =
+ MemoryDescriptor->MemoryEntry.MemoryType;
+
+ FwMemoryTable[FwMemoryFree-1].MemoryEntry.BasePage = BasePage +
+ PageCount;
+
+ FwMemoryTable[FwMemoryFree-1].MemoryEntry.PageCount =
+ MemoryDescriptor->MemoryEntry.PageCount -
+ (PageCount + Offset);
+
+ InsertTailList(&FwMemoryListHead,
+ &FwMemoryTable[FwMemoryFree-1].ListEntry);
+
+
+ MemoryDescriptor->MemoryEntry.PageCount = Offset;
+ }
+ }
+
+ return;
+}
+
+VOID
+FwResetMemory(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine calls FwInitializeMemory to reset the memory descriptors
+ and then loops through and clears all of the appropriate memory.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PMEMORY_DESCRIPTOR MemoryDescriptor;
+
+ FwInitializeMemory();
+
+ MemoryDescriptor = FwGetMemoryDescriptor(NULL);
+
+ while (MemoryDescriptor != NULL) {
+
+ if ((MemoryDescriptor->MemoryType != MemoryFirmwarePermanent) &&
+ (MemoryDescriptor->MemoryType != MemoryFirmwareTemporary) &&
+ (MemoryDescriptor->MemoryType != MemoryBad)) {
+
+ RtlZeroMemory((PVOID)(KSEG0_BASE + (MemoryDescriptor->BasePage << PAGE_SHIFT)),
+ MemoryDescriptor->PageCount << PAGE_SHIFT);
+ }
+
+ MemoryDescriptor = FwGetMemoryDescriptor(MemoryDescriptor);
+ }
+
+ //
+ // Sweep the data cache
+ //
+
+ HalSweepDcache();
+
+}
+
+ARC_STATUS
+FwRememberEisaBuffer (
+ IN ULONG PageAddress,
+ IN ULONG PageCount
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is used by the EISA configuration code in eisaini.c
+ to remember EISA memory buffers. This information is used on the
+ Alpha AXP/Jensen product for memory initialization.
+
+ Jensen I/O in the firmware, OSloader, and HAL bypasses the
+ region from .5MB -- 1MB to get around the DMA address -- EISA address
+ aliasing problem. So, this function does not have to mark buffers
+ within this region as bad.
+
+Arguments:
+
+ PageAddress The base address of the memory region, in pages.
+ PageCount The size of the region, in pages.
+
+Return Value:
+
+ ESUCCESS if all went well. Otherwise, an error code.
+
+--*/
+
+{
+ //
+ // Return if the address is within the .5MB -- 1MB region, which
+ // on Jensen is manually circumvented by firmware or HAL code.
+ //
+
+ if ((PageAddress >= (_512_KB >> PAGE_SHIFT)) &&
+ ((PageAddress + PageCount) < (ONE_MB >> PAGE_SHIFT))) {
+
+ return(ESUCCESS);
+ }
+
+ //
+ // Return error if there is no space left in the list.
+ //
+
+ if (EISABufferListPointer == FW_MEMORY_TABLE_SIZE) {
+ return(ENOMEM);
+ }
+
+ //
+ // Debug output --- will eventually be deleted.
+ //
+
+ FwPrint(FW_MARKING_EISA_BUFFER_MSG,
+ PageAddress << PAGE_SHIFT, PageCount << PAGE_SHIFT);
+ FwStallExecution(1000000);
+
+ EISABuffersToBeMarked[EISABufferListPointer].PageAddress = PageAddress;
+ EISABuffersToBeMarked[EISABufferListPointer].PageCount = PageCount;
+
+ EISABufferListPointer++;
+
+ return(ESUCCESS);
+
+}
+
+ARC_STATUS
+EisaMarkBadMemory (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is used by FwInitializeMemory to use the information stored
+ in EISABuffersToBeMarked to mark certain sections of memory as Bad
+ for the Alpha AXP/Jensen product.
+
+Arguments:
+
+ PageAddress The base address of the memory region, in pages.
+ PageCount The size of the region, in pages.
+
+Return Value:
+
+ ESUCCESS if all went well. Otherwise, an error code.
+
+--*/
+
+{
+ PFW_MEMORY_DESCRIPTOR FwMemoryDescriptor;
+ PMEMORY_DESCRIPTOR MemoryDescriptor;
+ ULONG I;
+ ULONG PageAddress;
+ ULONG PageCount;
+
+
+ if (EISABufferListPointer == 0) {
+ return(ESUCCESS);
+ }
+
+ for (I = 0; I < EISABufferListPointer; I++) {
+
+ //
+ // Get the base page address and page count of this buffer.
+ //
+
+ PageAddress = EISABuffersToBeMarked[I].PageAddress;
+ PageCount = EISABuffersToBeMarked[I].PageCount;
+
+
+ //
+ // If this EISA buffer is within an existing memory region,
+ // find it.
+ //
+
+ MemoryDescriptor = ArcGetMemoryDescriptor(NULL);
+
+ while (MemoryDescriptor != NULL){
+
+ if ((PageAddress >= MemoryDescriptor->BasePage) &&
+ ((PageAddress + PageCount) <=
+ (MemoryDescriptor->BasePage + MemoryDescriptor->PageCount))) {
+ break;
+ }
+
+ MemoryDescriptor = ArcGetMemoryDescriptor(MemoryDescriptor);
+ }
+
+ if (MemoryDescriptor != NULL) {
+
+ //
+ // The buffer is within an existing memory region.
+ //
+
+ FwMemoryDescriptor = CONTAINING_RECORD(MemoryDescriptor,
+ FW_MEMORY_DESCRIPTOR,
+ MemoryEntry);
+
+ FwGenerateDescriptor(FwMemoryDescriptor,
+ MemoryBad,
+ PageAddress,
+ PageCount);
+
+ } else if ((PageAddress << PAGE_SHIFT) >= MemorySize) {
+
+ //
+ // The buffer is beyond the end of memory. Create a
+ // descriptor for it.
+ //
+
+ INCREMENT_FWMEMORYFREE;
+
+ FwMemoryTable[FwMemoryFree-1].MemoryEntry.MemoryType = MemoryBad;
+ FwMemoryTable[FwMemoryFree-1].MemoryEntry.BasePage = PageAddress;
+ FwMemoryTable[FwMemoryFree-1].MemoryEntry.PageCount = PageCount;
+ InsertTailList(&FwMemoryListHead,
+ &FwMemoryTable[FwMemoryFree-1].ListEntry);
+
+ } else {
+
+ //
+ // The EISA buffer is not within an existing descriptor, and it
+ // is not beyond normal physical memory. Hence, the descriptors
+ // are too fragemented to mark this buffer.
+ //
+
+ FwPrint(FW_MARKING_EISA_BUFFER_ERROR_MSG,
+ EISABufferListPointer, I, PageAddress, PageCount);
+ return(ENOMEM);
+
+ }
+ }
+
+ return(ESUCCESS);
+}
diff --git a/private/ntos/fw/alpha/jensen/alpha/led.h b/private/ntos/fw/alpha/jensen/alpha/led.h
new file mode 100644
index 000000000..8100eb813
--- /dev/null
+++ b/private/ntos/fw/alpha/jensen/alpha/led.h
@@ -0,0 +1,36 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ led.h
+
+Abstract:
+
+ This module defines test and subtest values to display in the Jensen
+ hexadecimal LED display.
+
+ These will have to be segregated by #ifdef's when we port future
+ Alpha machines.
+
+Author:
+
+ 7-April-1992 John DeRosa
+
+Revision History:
+
+--*/
+
+
+
+#define LED_NT_BOOT_START 0x0 // NT firwmare has started executing
+#define LED_SERIAL_INIT 0x1 // We are initing the serial port
+#define LED_BROKEN_VIDEO_OR_KB 0x2 // Video or keyboard is broken.
+ // I/O is to serial lines
+#define LED_KEYBOARD_CTRL 0x3 // We are initing the keyboard
+ // and video.
+#define LED_VIDEO_OK 0x4 // Video and keyboard are OK.
+#define LED_OMEGA 0x5 // Firmware exited, we are in hang
+ // loop
+#define LED_FW_INITIALIZED 0x7 // Firmware is fully initialized
diff --git a/private/ntos/fw/alpha/jensen/alpha/machdef.h b/private/ntos/fw/alpha/jensen/alpha/machdef.h
new file mode 100644
index 000000000..36af44ffc
--- /dev/null
+++ b/private/ntos/fw/alpha/jensen/alpha/machdef.h
@@ -0,0 +1,83 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ machdef.h
+
+Abstract:
+
+ This module is the header file for machine-specific definitions
+ for the DECpc AXP 150 (Jensen) platform.
+
+
+Author:
+
+ David Orbits et. al. June 1993
+
+
+Revision History:
+
+--*/
+
+#ifndef _MACHDEF_
+#define _MACHDEF_
+
+//
+// Machine definition file for JENSEN platform.
+//
+// Each Alpha platform has its own machdef.h. Common C code need only
+// include machdef.h. The build procedure will pull in the correct
+// machdef.h for that platform.
+//
+//
+
+#include "jnsndef.h"
+
+
+//
+// Definitions that we want to keep private to the firmware directories.
+//
+
+#define FwpWriteIOChip HalpWriteVti
+#define FwpReadIOChip HalpReadVti
+
+//
+// The QVA base of Jensen EISA I/O space (CSRs).
+//
+
+#define EISA_IO_BASE_QVA 0xb8000000
+
+//
+// The QVA base of Jensen EISA memory space.
+//
+
+#define EISA_MEM_BASE_QVA 0xb0000000
+
+
+//
+// Macro for creating I/O port (CSR register) address.
+//
+// Port is the Intel 16 bit I/O space address
+//
+
+#define EisaIOQva(Port) (EISA_IO_BASE_QVA | (Port))
+
+//
+// Macro for creating I/O memory address.
+//
+// Port is the Intel 16 bit I/O space address
+//
+
+#define EisaMemQva(Port) (EISA_MEM_BASE_QVA | (Port))
+
+//
+// Number of physical EISA slots
+// (for Jensen and Culzean.)
+//
+
+#define PHYS_0_SLOTS 8
+
+
+#endif // _MACHDEF_
diff --git a/private/ntos/fw/alpha/jensen/alpha/selftest.c b/private/ntos/fw/alpha/jensen/alpha/selftest.c
new file mode 100644
index 000000000..1623acbf9
--- /dev/null
+++ b/private/ntos/fw/alpha/jensen/alpha/selftest.c
@@ -0,0 +1,599 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ selftest.c
+
+Abstract:
+
+ This module contains the routines that perform the selftest of
+ the IO devices.
+
+Author:
+
+ Lluis Abello (lluis) 03-Jan-1991
+
+Environment:
+
+
+Revision History:
+
+ 23-April-1992 John DeRosa [DEC]
+
+ Added Alpha/Jensen modifications. For Jensen, the VMS/OSF console
+ front-end will be running the ROM-based diagnostics so this code
+ does not have to do it.
+
+
+--*/
+
+#include "fwp.h"
+#include "iodevice.h"
+#include "led.h"
+#include "selftest.h"
+#include "fwpexcpt.h"
+#include "fwstring.h"
+
+BOOLEAN ConfigurationBit; // read value from diagnostic register
+
+PRTL_ALLOCATE_STRING_ROUTINE RtlAllocateStringRoutine =
+ (PRTL_ALLOCATE_STRING_ROUTINE)FwAllocatePool;
+PRTL_FREE_STRING_ROUTINE RtlFreeStringRoutine = FwpFreeStub;
+
+
+VOID
+FwInstallKd(
+ IN VOID
+ );
+
+
+#ifdef ALPHA_FW_SERDEB
+//
+// Variable that enables printing on the COM1 line.
+//
+extern BOOLEAN SerSnapshot;
+#endif
+
+
+// This variable is initialized to the size of the memory in bytes.
+ULONG MemorySize;
+
+
+//
+// This receives the type of video card installed into the system.
+// It is a static because memory is intialized near the bottom of the
+// program execute calling chain (FwExecute, FwPrivateExecute, FwResetMemory,
+// FwInitializeMemory), and the calling interface to FwExecute is
+// frozen by the ARCS specification.
+//
+// This is valid only on a successful intialization of the graphics card.
+//
+ALPHA_VIDEO_TYPE VideoType;
+
+
+// The indicator of a bad Firmware stack for _RtlCheckStack
+ULONG FwRtlStackPanic;
+
+#ifdef ALPHA_FW_VDB
+//
+// Debugging Aid
+//
+extern UCHAR DebugAid[2][150];
+#endif
+
+extern ULONG EISABufferListPointer;
+
+//
+// Alpha AXP PALcode static variables
+//
+
+// The processor type
+ULONG ProcessorId;
+
+// The processor revision number.
+ULONG ProcessorRevision;
+
+// The number of physical address bits.
+ULONG NumberOfPhysicalAddressBits;
+
+// The maximum address space number.
+ULONG MaximumAddressSpaceNumber;
+
+// The processor cycle counter period.
+ULONG ProcessorCycleCounterPeriod;
+
+// Number of processor cycles per microsecond.
+ULONG CyclesPerMicrosecond;
+
+// The processor page size, in bytes.
+ULONG ProcessorPageSize;
+
+// The system revision number
+ULONG SystemRevisionId;
+
+//
+// Declare function prototypes.
+//
+
+VOID
+PutLedDisplay(
+ IN UCHAR Value
+ );
+
+ULONG
+RomInitISP (
+ VOID
+ );
+
+ARC_STATUS
+SerialBootWrite(
+ CHAR Char,
+ ULONG SP
+ );
+
+VOID
+WildZeroMemory(
+ ULONG StartAddress,
+ ULONG Size
+ );
+
+VOID
+FwBootSystem (
+ VOID
+ );
+
+VOID
+FwEntry(
+ IN ULONG Cause,
+ IN PFW_PROCESSOR_INFORMATION ProcessorInfo,
+ IN PFW_SYSTEM_INFORMATION SystemInfo
+ )
+/*++
+
+Routine Description:
+
+ This routine is the c routine called from the ROM. It must be placed
+ at the beginning of the C code because the ROM copies the code from this
+ point to the end and then jumps to it.
+
+ This has a different calling interface than the Jazz code.
+
+
+Arguments:
+
+ Cause 0 on a normal reset/powerup.
+ 1 on a softreset.
+
+ ProcessorInfo Pointer to processor information block.
+ Valid only if Cause = 0.
+
+ SystemInfo Pointer to system information block.
+ Valid only if Cause = 0.
+
+
+Return Value:
+
+ Never returns.
+
+--*/
+
+{
+#if 0
+// Diagnostic bits turned off in final product.
+ CHAR Diag;
+#endif
+
+ FwRtlStackPanic = 0;
+
+ // Register exception handler with the firmware PALcode
+ RegisterExceptionHandler();
+
+ // Reset EISA memory buffer list.
+ EISABufferListPointer = 0;
+
+ // Clear out upper EISA address bits.
+ WRITE_PORT_UCHAR((PUCHAR)HAE, 0x0);
+
+ // Announce that the NT firmware has gotten control of the horizontal.
+ PutLedDisplay(LED_NT_BOOT_START);
+
+ // We cannot rely on the static C initialization of this if we are
+ // doing a soft-reset.
+ FwConsoleInitialized = FALSE;
+
+ //
+ // Deposit Alpha AXP architectural values into global variables if
+ // this is a hard reset.
+ //
+
+ if (Cause == 0) {
+ ProcessorId = ProcessorInfo->ProcessorId;
+ ProcessorRevision = ProcessorInfo->ProcessorRevision;
+ ProcessorPageSize = ProcessorInfo->PageSize;
+ NumberOfPhysicalAddressBits = ProcessorInfo->PhysicalAddressBits;
+ MaximumAddressSpaceNumber = ProcessorInfo->MaximumAddressSpaceNumber;
+ SystemRevisionId = SystemInfo->SystemRevisionId;
+
+ switch (SystemInfo->SystemCycleClockPeriod) {
+
+ //
+ // A bad cycle clock period would cause a system hang.
+ //
+ case 0:
+ case 8000:
+ default:
+ ProcessorCycleCounterPeriod = 8000;
+ break;
+
+ //
+ // This is an AX04 SROM bug: the number for a 6.667ns machine is
+ // passed in as 6600, not 6667.
+ //
+ case 6600:
+ case 6667:
+ ProcessorCycleCounterPeriod = 6667;
+ break;
+ }
+
+ //
+ // Load the number of machine cycles per usecond, for use by
+ // FwStallExecution. The +1 ensures that this value is never
+ // too optimistic, due to the float->integer truncation.
+ //
+
+ CyclesPerMicrosecond = (1000000 / ProcessorCycleCounterPeriod) + 1;
+
+ MemorySize = SystemInfo->MemorySizeInBytes;
+ }
+
+ //
+ // Set variables according to the bits in configuration register
+ //
+ ConfigurationBit = FALSE;
+ DisplayOutput = FALSE;
+ SerialOutput = FALSE;
+
+ //
+ // Look for configuration register.
+ //
+
+#if 0
+//
+// The ConfigurationBit is disabled in the product.
+//
+ HalpWriteVti(RTC_APORT, RTC_RAM_NT_FLAGS0);
+ Diag = HalpReadVti(RTC_DPORT);
+ if (((PRTC_RAM_NT_FLAGS_0)(&Diag))->ConfigurationBit) {
+ ConfigurationBit = TRUE;
+ }
+#endif
+
+
+ //
+ // Set interrupt lines to a known state.
+ //
+
+ WRITE_PORT_UCHAR((PUCHAR)&SP1_WRITE->ModemControl,0x08);
+ WRITE_PORT_UCHAR((PUCHAR)&SP2_WRITE->ModemControl,0x08);
+ WRITE_PORT_UCHAR((PUCHAR)&FLOPPY_WRITE->DigitalOutput,0x08);
+ READ_PORT_UCHAR((PUCHAR)&PARALLEL_READ->Status);
+
+ //
+ // Initialize the system parameter block.
+ //
+
+ SYSTEM_BLOCK->Signature = 0x53435241;
+ SYSTEM_BLOCK->Length = sizeof(SYSTEM_PARAMETER_BLOCK);
+ SYSTEM_BLOCK->Version = ARC_VERSION;
+ SYSTEM_BLOCK->Revision = ARC_REVISION;
+ SYSTEM_BLOCK->DebugBlock = NULL;
+
+ SYSTEM_BLOCK->FirmwareVectorLength = (ULONG)MaximumRoutine * sizeof(ULONG);
+ SYSTEM_BLOCK->FirmwareVector =
+ (PVOID)((PUCHAR)SYSTEM_BLOCK + sizeof(SYSTEM_PARAMETER_BLOCK));
+ SYSTEM_BLOCK->VendorVectorLength = (ULONG)MaximumVendorRoutine * sizeof(ULONG);
+ SYSTEM_BLOCK->VendorVector =
+ (PVOID)((PUCHAR)SYSTEM_BLOCK->FirmwareVector +
+ SYSTEM_BLOCK->FirmwareVectorLength);
+
+ //
+ // Always init the serial ports, because the NT Setup utility sends
+ // diagnostics there.
+ //
+
+ PutLedDisplay(LED_SERIAL_INIT);
+ SerialBootSetup(COMPORT1_VIRTUAL_BASE);
+ SerialBootSetup(COMPORT2_VIRTUAL_BASE);
+
+#ifdef ALPHA_FW_KDHOOKS
+
+ //
+ // Initialize the kernel debugger stub. This can be called anytime
+ // after the serial lines are inited.
+ //
+
+ FwInstallKd();
+
+#endif
+
+ //
+ // If: the configuration bit is set, or
+ // the video card initialization fails,
+ // ...output to the serial line. Otherwise, output to video.
+ //
+
+ PutLedDisplay (LED_KEYBOARD_CTRL);
+ if (ConfigurationBit || (DisplayBootInitialize(&VideoType) != ESUCCESS)) {
+ SerialOutput = TRUE;
+ PutLedDisplay(LED_BROKEN_VIDEO_OR_KB);
+ FwClearScreen();
+ } else {
+ // Video is ready to display messages.
+ PutLedDisplay(LED_VIDEO_OK);
+ DisplayOutput = TRUE;
+ }
+
+
+ //
+ // If: the keyboard controller initialization fails, or
+ // the keyboard initialization fails,
+ // ...send an error message to the output device and direct future output
+ // to the serial port.
+ //
+
+ if (InitKeyboardController() || InitKeyboard()) {
+ FwPrint(ST_ALL_IO_TO_SERIAL_LINES_MSG);
+ PutLedDisplay(LED_BROKEN_VIDEO_OR_KB);
+ DisplayOutput = FALSE;
+ SerialOutput = TRUE;
+ }
+
+
+#ifdef ALPHA_FW_SERDEB
+#ifdef ALPHA_FW_VDB
+
+{
+ //
+ // Graphics debugging assistance. Print pre-init and post-init video
+ // state.
+ //
+
+ ULONG H, I, J;
+
+ SerSnapshot = TRUE;
+
+ for (J = 0; J < 8; J++) {
+
+ for (H = 0; H < 2; H++) {
+
+ SerFwPrint("[%d:%d] = ", H, J*16);
+
+ for (I = J*16; I < (J+1)*16; I++) {
+ SerFwPrint("%x ", DebugAid[H][I]);
+ }
+
+ SerFwPrint("\r\n");
+ }
+
+ }
+
+}
+
+#endif
+#endif
+
+
+ //
+ // Check for Alpha AXP architectural values that are obviously bad.
+ //
+
+ if (Cause == 0) {
+ if (ProcessorInfo->PageSize != PAGE_SIZE) {
+ FwPrint(ST_BAD_PAGE_SIZE_MSG, ProcessorInfo->PageSize);
+ FwStallExecution(5 * 1000 * 1000);
+ }
+ if (SystemInfo->MemorySizeInBytes < FOUR_MB) {
+ FwPrint(ST_BAD_MEMORY_SIZE_MSG, SystemInfo->MemorySizeInBytes);
+ FwStallExecution(5 * 1000 * 1000);
+ }
+ if (SystemInfo->SystemCycleClockPeriod == 0) {
+ FwPrint(ST_BAD_CLOCK_PERIOD_MSG, ProcessorCycleCounterPeriod);
+ FwStallExecution(5 * 1000 * 1000);
+ }
+ }
+
+ if (RomInitISP()) {
+ FwPrint(ST_EISA_ISP_ERROR_MSG);
+ }
+
+
+#if 0
+
+ //
+ // This is not necessary.
+ //
+
+ //
+ // Zero unused memory.
+ //
+ // This is dependent on the firmware memory map.
+ // This could be made more independent via using #define's.
+ //
+
+ WildZeroMemory(
+ (KSEG0_BASE | 0x0),
+ (FW_BOTTOM_ADDRESS - 0x40000)
+ );
+
+ WildZeroMemory(
+ (KSEG0_BASE | FW_TOP_ADDRESS),
+ (MemorySize - FW_TOP_ADDRESS)
+ );
+
+#endif
+
+ FwBootSystem();
+
+ //
+ // Hang if we come back.
+ //
+
+ for (;;) {
+ PutLedDisplay(LED_OMEGA);
+ }
+
+}
+
+VOID
+PutLedDisplay(
+ IN UCHAR Value
+ )
+/*++
+
+Routine Description:
+
+ This displays a 0--F in the single hexadecimal digit display in
+ Jensen.
+
+Arguments:
+
+ Value The lower four bits of this will be displayed
+ in the Jensen LED.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ WRITE_PORT_UCHAR ((PUCHAR)SYSCTL,
+ (READ_PORT_UCHAR((PUCHAR)SYSCTL) & 0xf0)
+ |
+ (Value & 0x0f)
+ );
+ }
+
+ULONG
+RomInitISP (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the EISA interrupt controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns the number of errors found.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ UCHAR InterruptLevel;
+
+ //
+ // Initialize the EISA interrupt controller. There are two cascaded
+ // interrupt controllers, each of which must initialized with 4 initialize
+ // control words.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ WRITE_PORT_UCHAR((PUCHAR)&EISA_CONTROL->Interrupt1ControlPort0,DataByte);
+ WRITE_PORT_UCHAR((PUCHAR)&EISA_CONTROL->Interrupt2ControlPort0,DataByte);
+
+ //
+ // The second intitialization control word sets the interrupt vector to
+ // 0-15.
+ //
+
+ DataByte = 0;
+
+ WRITE_PORT_UCHAR((PUCHAR)&EISA_CONTROL->Interrupt1ControlPort1,DataByte);
+
+ DataByte = 0x08;
+
+ WRITE_PORT_UCHAR((PUCHAR)&EISA_CONTROL->Interrupt2ControlPort1,DataByte);
+
+ //
+ // The third initialization control word set the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a numeric.
+ //
+
+ DataByte = 1 << SLAVE_IRQL_LEVEL;
+
+ WRITE_PORT_UCHAR((PUCHAR)&EISA_CONTROL->Interrupt1ControlPort1,DataByte);
+
+ DataByte = SLAVE_IRQL_LEVEL;
+
+ WRITE_PORT_UCHAR((PUCHAR)&EISA_CONTROL->Interrupt2ControlPort1,DataByte);
+
+ //
+ // The fourth initialization control word is used to specify normal
+ // end-of-interrupt mode and not special-fully-nested mode.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1;
+
+ WRITE_PORT_UCHAR((PUCHAR)&EISA_CONTROL->Interrupt1ControlPort1,DataByte);
+ WRITE_PORT_UCHAR((PUCHAR)&EISA_CONTROL->Interrupt2ControlPort1,DataByte);
+
+
+ //
+ // Mask all the interrupts.
+ //
+ WRITE_PORT_UCHAR((PUCHAR)&EISA_CONTROL->Interrupt1ControlPort1,0xFF);
+ WRITE_PORT_UCHAR((PUCHAR)&EISA_CONTROL->Interrupt2ControlPort1,0xFF);
+
+
+#if 0
+ //
+ // Jazz code
+ //
+
+ //
+ // Check that the interrupt level is 7 (i.e. no interrupt is pending)
+ //
+ InterruptLevel=READ_PORT_UCHAR((PUCHAR)&DMA_CONTROL->InterruptAcknowledge);
+ InterruptLevel=READ_PORT_UCHAR((PUCHAR)&DMA_CONTROL->InterruptAcknowledge);
+
+ if (InterruptLevel == 0x07) {
+ return 0;
+ } else {
+ return 1;
+ }
+#else
+
+ //
+ // Alpha/Jensen code
+ //
+
+ //
+ // Check that no interrupts are pending.
+ //
+
+ WRITE_PORT_UCHAR((PUCHAR)&EISA_CONTROL->Interrupt1ControlPort0, 0xA);
+ InterruptLevel = READ_PORT_UCHAR((PUCHAR)&EISA_CONTROL->Interrupt1ControlPort0);
+ WRITE_PORT_UCHAR((PUCHAR)&EISA_CONTROL->Interrupt2ControlPort0, 0xA);
+ InterruptLevel |= READ_PORT_UCHAR((PUCHAR)&EISA_CONTROL->Interrupt2ControlPort0);
+
+ return(InterruptLevel);
+#endif
+
+}
diff --git a/private/ntos/fw/alpha/jensen/alpha/tbaqva.c b/private/ntos/fw/alpha/jensen/alpha/tbaqva.c
new file mode 100644
index 000000000..5a5475985
--- /dev/null
+++ b/private/ntos/fw/alpha/jensen/alpha/tbaqva.c
@@ -0,0 +1,413 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ tbaqva.c
+
+Abstract:
+
+ This module contains the platform dependent code to create bus addreses
+ and QVAs.
+
+Author:
+
+ Jeff McLeman (mcleman) 27-May-1992
+ David Orbits 7-June-1992
+
+Environment:
+
+ Kernel mode, local to I/O system
+
+Revision History:
+
+ John DeRosa [DEC] 15-June-1993
+
+ These differ from the HAL versions in that EISA memory addresses above
+ 32MB are not mapped, and there is no tracking of multiple HAE values.
+
+--*/
+
+#include "fwp.h"
+#include "ntalpha.h"
+#include "jxfwhal.h"
+#include "jnsndma.h"
+#include "eisa.h"
+#include "jxisa.h"
+
+
+
+#define HAL_32MB 0x2000000
+
+
+
+QUASI_VIRTUAL_ADDRESS
+HalCreateQva(
+ IN PHYSICAL_ADDRESS PA,
+ IN PVOID VA
+ );
+
+
+BOOLEAN
+HalTranslateBusAddress(
+ IN INTERFACE_TYPE InterfaceType,
+ IN ULONG BusNumber,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system physical address for a specified I/O bus
+ address. The return value is suitable for use in a subsequent call to
+ MmMapIoSpace.
+
+Arguments:
+
+ InterfaceType - Supplies the type of bus which the address is for.
+
+ BusNumber - Supplies the bus number for the device; not used in Jensen
+
+ BusAddress - Supplies the bus relative address.
+
+ AddressSpace - Supplies the address space number for the device: 0 for
+ memory and 1 for I/O space. If the desired access mode is user mode,
+ then bit 1 must be TRUE.
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+
+Notes:
+
+ This is a variation of what began in the MIPS code. The intel code often
+ assumes that if an address is in I/O space, the bottom 32 bits of the
+ physical address can be used "like" a virtual address, and are returned
+ to the user. This doesn't work on MIPs machines where physical
+ addresses can be larger than 32 bits.
+
+ Since we are using superpage addresses for I/O on Alpha, we can do
+ almost what is done on intel. If AddressSpace is equal to 0 or 1, then
+ we assume the user is doing kernel I/O and we call
+ HalCreateQva to build a Quasi Virtual Address and return
+ that to the caller. We then set AddressSpace to a 1, so that the caller
+ will not call MmMapIoSpace. The Caller will use the low 32 bits of the
+ physical address we return as the VA. (Which we built a QVA in).
+ If the caller wants to access EISA I/O or Memory through user mode, then
+ the caller must set bit 1 in AddressSpace to a 1 (AddressSpace=2 or 3,
+ depending on whether EISA I/O or Memory), then the caller is returned the
+ 34 bit Physical address. The caller will then call MmMapIoSpace, or
+ ZwMapViewOfSection which in turn calls HalCreateQva to build a QVA out
+ of a VA mapped through the page tables.
+
+ **** Note ****
+
+ The QVA in user mode can only be accessed with the routines WRITE/READ_
+ REGISTER_UCHAR/USHORT/ULONG, and they must be the ones in module
+ JXIOUSER.C. The user CANNOT call the above routines in the HAL from
+ usermode. (Which is pointless, since the HAL is superpage access
+ only).
+
+
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ PVOID va = 0; // note, this is used for a placeholder
+
+ //
+ // If this is for the internal bus then the device is on the combo chip.
+ // BusAddress.LowPart should contains the port of the device.
+ //
+
+ if (InterfaceType == Internal) {
+
+ //
+ // Return the passed parameters.
+ //
+
+ TranslatedAddress->HighPart = 1;
+ TranslatedAddress->LowPart = 0xC0000000 + (BusAddress.LowPart << COMBO_BIT_SHIFT);
+
+ //
+ // Now call HalCreateQva. This will create a QVA
+ // that we'll return to the caller. Then we will implicitly set
+ // AddressSpace to a 1. The caller then will not call MmMapIoSpace
+ // and will use the address we return as a VA.
+
+ TranslatedAddress->LowPart = (ULONG) HalCreateQva(
+ *TranslatedAddress, va);
+
+ TranslatedAddress->HighPart = 0; // clear high longword for QVA
+
+ *AddressSpace = 1; // Make sure user doesn't call
+ // MmMapIoSpace.
+
+ return(TRUE);
+ }
+
+ if (InterfaceType != Isa && InterfaceType != Eisa) {
+
+ //
+ // Not on this system return nothing.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+
+ //
+ // Jensen only has one I/O bus which is an EISA, so the bus number is unused.
+ //
+ // Determine the address based on whether the bus address is in I/O space
+ // or bus memory space.
+ //
+
+
+ switch (*AddressSpace) {
+
+ case 0 : {
+
+ //
+ // The address is in EISA memory space, kernel mode.
+ //
+
+ //
+ // If the address cannot be mapped, just return FALSE.
+ //
+ if ( BusAddress.LowPart > HAL_32MB ) {
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+
+ }
+
+ TranslatedAddress->HighPart = 0x2;
+
+ //
+ // There is no component of the bus address in the low part
+ //
+ TranslatedAddress->LowPart = (BusAddress.LowPart << EISA_BIT_SHIFT);
+
+ //
+ // Now call HalCreateQva. This will create a QVA
+ // that we'll return to the caller. Then we will implicitly set
+ // AddressSpace to a 1. The caller then will not call MmMapIoSpace
+ // and will use the address we return as a VA.
+
+ TranslatedAddress->LowPart = (ULONG) HalCreateQva(
+ *TranslatedAddress, va);
+
+ TranslatedAddress->HighPart = 0; // clear high longword for QVA
+
+ *AddressSpace = 1; // don't let the user call MmMapIoSpace
+
+ return(TRUE);
+
+ }
+
+ case 1 : {
+ //
+ // The address is in EISA I/O space, kernel mode.
+ //
+
+ TranslatedAddress->HighPart = 0x3;
+ //
+ // There is no component of the bus address in the low part
+ //
+ TranslatedAddress->LowPart = (BusAddress.LowPart << EISA_BIT_SHIFT);
+
+
+ //
+ // Now call HalCreateQva. This will create a QVA
+ // that we'll return to the caller. Then we will implicitly set
+ // AddressSpace to a 1. The caller then will not call MmMapIoSpace
+ // and will use the address we return as a VA.
+
+ TranslatedAddress->LowPart = (ULONG) HalCreateQva(
+ *TranslatedAddress, va);
+
+ TranslatedAddress->HighPart = 0; // clear high longword for QVA
+
+ *AddressSpace = 1; // Make sure user doesn't call
+ // MmMapIoSpace.
+
+ return(TRUE);
+
+ }
+ case 2 : {
+
+ //
+ // The address is in EISA memory space, user mode.
+ //
+
+
+ TranslatedAddress->HighPart = 0x2;
+
+
+ //
+ // There is no component of the bus address in the low part
+ //
+ TranslatedAddress->LowPart = (BusAddress.LowPart << EISA_BIT_SHIFT);
+
+
+ *AddressSpace = 0; // Let the user call MmMapIoSpace
+
+ return(TRUE);
+
+ }
+
+ case 3 : {
+ //
+ // The address is in EISA I/O space, user mode.
+ //
+
+ TranslatedAddress->HighPart = 0x3;
+ //
+ // There is no component of the bus address in the low part
+ //
+ TranslatedAddress->LowPart = (BusAddress.LowPart << EISA_BIT_SHIFT);
+
+
+ *AddressSpace = 0; // Make sure user can call
+ // MmMapIoSpace.
+
+ return(TRUE);
+
+ }
+
+ }
+}
+
+PVOID
+HalCreateQva(
+ IN PHYSICAL_ADDRESS PA,
+ IN PVOID VA
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called two ways. First, from HalTranslateBusAddress,
+ if the caller is going to run in kernel mode and use superpages.
+ The second way is if the user is going to access in user mode.
+ MmMapIoSpace or ZwViewMapOfSection will call this.
+
+ If the input parameter VA is zero, then we assume super page and build
+ a QUASI virtual address that is only usable by calling the hal I/O
+ access routines.
+
+ if the input parameter VA is non-zero, we assume the user has either
+ called MmMapIoSpace or ZwMapViewOfSection and will use the access
+ routines in JXIOUSER.C
+
+ If the PA is not an I/O space address (Combo chip, Eisa I/O, Eisa
+ memory), then return the VA as the QVA.
+
+Arguments:
+
+ PA - the physical address generated by HalTranslateBusAddress
+
+ VA - the virtual address returned by MmMapIoSpace
+
+Return Value:
+
+ The returned value is a quasi virtual address in that it can be
+ added to and subtracted from, but it cannot be used to access the
+ bus directly. The top bits are set so that we can trap invalid
+ accesses in the memory management subsystem. All access should be
+ done through the Hal Access Routines in *ioacc.s if it was a superpage
+ kernel mode access. If it is usermode, then JXIOUSER.C should be built
+ into the users code.
+
+--*/
+{
+
+ PVOID qva;
+
+ if (PA.HighPart == 2) {
+
+ //
+ // in EISA MEMORY space
+ //
+
+ if (VA == 0) {
+
+ PA.LowPart = PA.LowPart >> 2;
+ qva = (PVOID)(RtlLargeIntegerShiftRight(PA, EISA_BIT_SHIFT-2).LowPart);
+
+ } else {
+
+ qva = (PVOID)((ULONG)VA >> EISA_BIT_SHIFT);
+ }
+
+ qva = (PVOID)((ULONG)qva | EISA_QVA);
+
+ return(qva);
+ }
+
+ if (PA.HighPart == 3) {
+
+ //
+ // in EISA IO space
+ //
+
+ if (VA == 0) {
+
+ PA.LowPart = PA.LowPart >> 2;
+ qva = (PVOID)(RtlLargeIntegerShiftRight(PA, EISA_BIT_SHIFT-2).LowPart);
+
+ } else {
+
+ qva = (PVOID)((ULONG)VA >> EISA_BIT_SHIFT);
+
+ }
+
+ qva = (PVOID)((ULONG)qva | EISA_QVA);
+
+ return(qva);
+ }
+
+ if (PA.HighPart == 1) {
+
+ //
+ // on the combo chip (82C106)
+ //
+
+ if (VA == 0) {
+
+ qva = (PVOID)(RtlLargeIntegerShiftRight(PA, COMBO_BIT_SHIFT).LowPart);
+
+ } else {
+
+ qva = (PVOID)((ULONG)VA >> COMBO_BIT_SHIFT);
+ }
+
+ qva = (PVOID)((ULONG)qva | COMBO_QVA);
+
+ return(qva);
+ }
+
+ //
+ // It is not an I/O space address, return the VA as the QVA
+ //
+
+ return(VA);
+
+}
diff --git a/private/ntos/fw/alpha/jensen/alpha/version.c b/private/ntos/fw/alpha/jensen/alpha/version.c
new file mode 100644
index 000000000..b68dd8f89
--- /dev/null
+++ b/private/ntos/fw/alpha/jensen/alpha/version.c
@@ -0,0 +1,34 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ version.c
+
+Abstract:
+
+ This module defines the revision of the code being linked. It should be
+ included in the firmware, fsb, and jnupdate builds.
+
+Author:
+
+ John DeRosa [DEC] 17-June-1993
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "fwp.h"
+//#include "machdef.h"
+//#include "string.h"
+
+//
+// Version number of this firmware package.
+//
+
+PCHAR FirmwareVersion = "1.12";
diff --git a/private/ntos/fw/alpha/jensen/alpha/xxstring.c b/private/ntos/fw/alpha/jensen/alpha/xxstring.c
new file mode 100644
index 000000000..654598877
--- /dev/null
+++ b/private/ntos/fw/alpha/jensen/alpha/xxstring.c
@@ -0,0 +1,91 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ xxstring.c
+
+Abstract:
+
+ This module contains language-independent, machine-specific strings.
+
+ These are filespec and ARC pathname strings. There is one of these
+ in each machine-specific subdirectory.
+
+Author:
+
+ John DeRosa and Ken Abramson 8-July-1993
+
+
+Revision History:
+
+
+--*/
+
+#include "ntos.h"
+
+
+//
+// Conftest. These strings are defined explicitly because conftest
+// must be a machine-independent application. The system firmware
+// files should NOT reference these strings directly, but instead use
+// one of the FW_ strings.
+//
+// These strings must not be changed for any specific machine builds.
+//
+
+PCHAR EISA_UNICODE_CONSOLE_OUT = "eisa()video()monitor()console(1)";
+PCHAR MULTI_UNICODE_CONSOLE_OUT = "multi()video()monitor()console(1)";
+PCHAR EISA_NORMAL_CONSOLE_OUT = "eisa()video()monitor()console()";
+PCHAR MULTI_NORMAL_CONSOLE_OUT = "multi()video()monitor()console()";
+PCHAR MULTI_UNICODE_KEYBOARD_IN = "multi()key()keyboard()console(1)";
+PCHAR MULTI_NORMAL_KEYBOARD_IN = "multi()key()keyboard()console()";
+
+
+//
+// These strings should be changed as necessary for builds of firmware
+// for specific Alpha AXP machines.
+//
+
+// Default keyboard in device.
+PCHAR FW_KEYBOARD_IN_DEVICE = "multi()key()keyboard()console()";
+
+// Default keyboard in device, without the "console()" section.
+PCHAR FW_KEYBOARD_IN_DEVICE_PATH = "multi(0)key(0)keyboard(0)";
+
+// Default video out device.
+PCHAR FW_CONSOLE_OUT_DEVICE = "eisa()video()monitor()console()";
+
+// Default video out display path, without the "console()" section.
+PCHAR FW_DISPLAY_DEVICE_PATH = "eisa(0)video(0)monitor(0)";
+
+// Default primary floppy device.
+PCHAR FW_FLOPPY_0_DEVICE = "eisa(0)disk(0)fdisk(0)";
+PCHAR FW_FLOPPY_0_FORMAT_DEVICE = "eisa(0)disk(%1d)fdisk(0)";
+
+// Default secondary floppy device.
+PCHAR FW_FLOPPY_1_DEVICE = "eisa()disk()fdisk(1)";
+
+#ifdef EISA_PLATFORM
+// Default location for ECU
+PCHAR FW_ECU_LOCATION = "eisa()disk()fdisk()ecu.exe";
+#endif
+
+// Default primary location of firmware update tool.
+PCHAR FW_PRIMARY_FIRMWARE_UPDATE_TOOL = "eisa()disk()fdisk()jnupdate.exe";
+
+// Filename of firmware update tool.
+PCHAR FW_FIRMWARE_UPDATE_TOOL_NAME = "\\jnupdate.exe";
+
+// The Component Data Structure node that is a child of the floppy controller.
+PCHAR FW_FLOPPY_PARENT_NODE = "eisa()";
+
+// The identifier to be given to the floppy controller in the CDS tree.
+PCHAR FW_FLOPPY_CDS_IDENTIFIER = "AHA1742-FLOPPY";
+
+// Default device path for serial port 0.
+PCHAR FW_SERIAL_0_DEVICE = "multi(0)serial(0)";
+
+// Default device path for serial port 1.
+PCHAR FW_SERIAL_1_DEVICE = "multi(0)serial(1)";
diff --git a/private/ntos/fw/alpha/jensen/be_firm.cmd b/private/ntos/fw/alpha/jensen/be_firm.cmd
new file mode 100644
index 000000000..94b9822a8
--- /dev/null
+++ b/private/ntos/fw/alpha/jensen/be_firm.cmd
@@ -0,0 +1,107 @@
+echo off
+goto start
+
+/******************************************************************
+
+NT/Alpha AXP firmware build script
+Copyright (c) 1993 Digital Equipment Corporation
+
+John DeRosa 16-July-1992
+
+
+This will compile and link the NT/Alpha AXP firmware package.
+
+At the moment this is geared to Jensen.
+
+
+Parameters:
+
+ -c says to do a build -c.
+
+*********************************************************************/
+
+
+:start
+
+rem
+rem Define variables used in the build process.
+rem
+
+rem The top-level of the working NT sources directory tree.
+set BuildPool=\nt
+
+
+
+rem
+rem Analyze command line parameters.
+rem
+
+set BuildSwitch=
+if "%1"=="-c" set BuildSwitch=-c
+
+
+rem
+rem Build the firmware.
+rem
+
+echo *** Building bldr files... ***
+cd %BuildPool%\private\ntos\bldr
+build %BuildSwitch%
+if not errorlevel 0 goto ERROREXIT
+
+echo *** Building hal files... ***
+cd %BuildPool%\private\ntos\nthals\hal0jens
+build %BuildSwitch%
+if not errorlevel 0 goto ERROREXIT
+
+echo *** Building rtl files... ***
+cd %BuildPool%\private\ntos\rtl
+build %BuildSwitch%
+if not errorlevel 0 goto ERROREXIT
+
+echo *** Building Jensen fw files... ***
+cd %BuildPool%\private\ntos\fw\alpha\jensen
+build %BuildSwitch%
+if not errorlevel 0 goto ERROREXIT
+
+goto NORMALEXIT
+
+
+rem
+rem Here on some kind of error.
+rem
+
+:ERROREXIT
+
+echo ???
+echo ??? ERROR during build. Build terminated with extreme prejudice.
+echo ???
+
+
+
+
+rem
+rem Here to exit the procedure.
+rem
+
+:NORMALEXIT
+
+
+copy %BuildPool%\private\ntos\bldr\build.log %BuildPool%\private\ntos\fw\alpha\jensen\be_firm.log
+type %BuildPool%\private\ntos\nthals\hal0jens\build.log >> %BuildPool%\private\ntos\fw\alpha\jensen\be_firm.log
+type %BuildPool%\private\ntos\rtl\build.log >> %BuildPool%\private\ntos\fw\alpha\jensen\be_firm.log
+rem
+rem type %BuildPool%\private\ntos\ke\build.log >> %BuildPool%\private\ntos\fw\alpha\jensen\be_firm.log
+rem
+type %BuildPool%\private\ntos\fw\alpha\jensen\build.log >> %BuildPool%\private\ntos\fw\alpha\jensen\be_firm.log
+
+echo *** Build done. Look in jensen\be_firm.log for merged build logs.
+echo *** Check the obj\alpha area.
+
+rem
+rem return to the firmware directory
+rem
+
+cd %BuildPool%\private\ntos\fw\alpha\jensen
+
+@echo on
diff --git a/private/ntos/fw/alpha/jensen/clean.cmd b/private/ntos/fw/alpha/jensen/clean.cmd
new file mode 100644
index 000000000..0e3da3adc
--- /dev/null
+++ b/private/ntos/fw/alpha/jensen/clean.cmd
@@ -0,0 +1,11 @@
+rem
+rem Delete all the autogenerated files in jensen\alpha.
+rem
+
+pushd \nt\private\ntos\fw\alpha\jensen\alpha
+
+del/f bldrstub.c conftest.c eisafunc.c eisaini.c eisamisc.c eisapod.c eisausa.c fakebldr.c fwchkstk.s fwhalt.c fwio.c fwkd.c fwload.c fwprint.c fwrstb.c fwsignal.c fwtime.c fwusa.c jenassem.s jenfonts.c jnfsinit.c jnfsstb.c jnfsstub.s jnsetcom.c jnsetenv.c jnsetmak.c jnsetset.c jnsettim.c jnupass.s jnupdate.c jnupstub.c jxboot.c jxconfig.c jxdisp.c jxenvir.c jxfboot.c jxhwsup.c jxkbd.c jxreboot.c jxserial.c jxsysid.c jxvendor.c kbdtest.c kdstubs.c monitor.c omf.c rom.c stubs.c ff* fs* u* fj*
+
+del/f ff* fs* u* fj*
+
+popd
diff --git a/private/ntos/fw/alpha/jensen/conftest.rsp b/private/ntos/fw/alpha/jensen/conftest.rsp
new file mode 100644
index 000000000..2e4242e52
--- /dev/null
+++ b/private/ntos/fw/alpha/jensen/conftest.rsp
@@ -0,0 +1,10 @@
+-machine:alpha
+-fixed
+-rom
+-base:0x80080000,0x80082a00
+-align:0x100
+-debug:full
+-debugtype:coff
+-entry:main
+obj\alpha\conftest.obj
+\nt\public\sdk\lib\alpha\libcnt.lib
diff --git a/private/ntos/fw/alpha/jensen/fakebldr.rsp b/private/ntos/fw/alpha/jensen/fakebldr.rsp
new file mode 100644
index 000000000..945430cd4
--- /dev/null
+++ b/private/ntos/fw/alpha/jensen/fakebldr.rsp
@@ -0,0 +1,10 @@
+-machine:alpha
+-fixed
+-rom
+-base:0x80600000,0x80600800
+-align:0x100
+-debug:full
+-debugtype:coff
+-entry:main
+obj\alpha\fakebldr.obj
+\nt\public\sdk\lib\alpha\libcnt.lib
diff --git a/private/ntos/fw/alpha/jensen/linkfsb.rsp b/private/ntos/fw/alpha/jensen/linkfsb.rsp
new file mode 100644
index 000000000..2998fe940
--- /dev/null
+++ b/private/ntos/fw/alpha/jensen/linkfsb.rsp
@@ -0,0 +1,48 @@
+-machine:alpha
+-rom
+-fixed
+-base:0x80704000
+-align:0x100
+-debug:full
+-debugtype:coff
+-entry:FailSafeEntry
+obj\alpha\jnfs.obj
+obj\alpha\jnfsinit.obj
+obj\alpha\jnfsstub.obj
+obj\alpha\version.obj
+obj\alpha\fjnsetcm.obj
+obj\alpha\fjxdisp.obj
+obj\alpha\fjxconfg.obj
+obj\alpha\fjxvendr.obj
+obj\alpha\ffwio.obj
+obj\alpha\fwprint.obj
+obj\alpha\fwload.obj
+obj\alpha\xxstring.obj
+obj\alpha\jxfboot.obj
+obj\alpha\fwtime.obj
+obj\alpha\fwusa.obj
+obj\alpha\fwsignal.obj
+obj\alpha\jxmemory.obj
+obj\alpha\kbdtest.obj
+obj\alpha\jxhwsup.obj
+obj\alpha\tbaqva.obj
+obj\alpha\jxkbd.obj
+obj\alpha\jnfsstb.obj
+obj\alpha\jxserial.obj
+obj\alpha\fwchkstk.obj
+obj\alpha\fjenfont.obj
+obj\alpha\fstubs.obj
+obj\alpha\jenstubs.obj
+obj\alpha\aha174x.obj
+..\..\..\bldr\obj\alpha\fatboot.obj
+..\..\..\bldr\obj\alpha\cdfsboot.obj
+..\..\..\bldr\obj\alpha\scsiboot.obj
+..\..\..\bldr\obj\alpha\scsidisk.obj
+..\..\..\rtl\obj\alpha\rtl.lib
+..\..\..\nthals\hal0jens\obj\alpha\axlbsup.obj
+..\..\..\nthals\hal0jens\obj\alpha\halpal.obj
+..\..\..\nthals\hal0jens\obj\alpha\jxcache.obj
+..\..\..\nthals\hal0jens\obj\alpha\jxioacc.obj
+..\..\..\nthals\hal0jens\obj\alpha\jxtime.obj
+..\..\..\nthals\hal0jens\obj\alpha\jxvtisup.obj
+\nt\public\sdk\lib\alpha\libcnt.lib
diff --git a/private/ntos/fw/alpha/jensen/linkjens.rsp b/private/ntos/fw/alpha/jensen/linkjens.rsp
new file mode 100644
index 000000000..56ca21fc8
--- /dev/null
+++ b/private/ntos/fw/alpha/jensen/linkjens.rsp
@@ -0,0 +1,67 @@
+-machine:alpha
+-rom
+-fixed
+-base:0x80704000
+-align:0x100
+-debug:full
+-debugtype:coff
+-entry:FwEntry
+obj\alpha\selftest.obj
+obj\alpha\version.obj
+obj\alpha\eisafunc.obj
+obj\alpha\eisaini.obj
+obj\alpha\eisamisc.obj
+obj\alpha\eisapod.obj
+obj\alpha\fwhalt.obj
+obj\alpha\bldrstub.obj
+obj\alpha\fwrstb.obj
+obj\alpha\fwio.obj
+obj\alpha\fwload.obj
+obj\alpha\fwprint.obj
+obj\alpha\fwtime.obj
+obj\alpha\fwsignal.obj
+obj\alpha\xxstring.obj
+obj\alpha\jenassem.obj
+obj\alpha\jnsetcfg.obj
+obj\alpha\jnsetcom.obj
+obj\alpha\jnsetenv.obj
+obj\alpha\jnsetmak.obj
+obj\alpha\jnsetset.obj
+obj\alpha\jnsettim.obj
+obj\alpha\jxboot.obj
+obj\alpha\jxconfig.obj
+obj\alpha\jxdisp.obj
+obj\alpha\jxenvir.obj
+obj\alpha\jxfboot.obj
+obj\alpha\jxhwsup.obj
+obj\alpha\jxkbd.obj
+obj\alpha\jxmemory.obj
+obj\alpha\jxreboot.obj
+obj\alpha\jxserial.obj
+obj\alpha\jxsysid.obj
+obj\alpha\jxvendor.obj
+obj\alpha\rom.obj
+obj\alpha\kbdtest.obj
+obj\alpha\monitor.obj
+obj\alpha\omf.obj
+obj\alpha\fwchkstk.obj
+obj\alpha\tbaqva.obj
+obj\alpha\jenfonts.obj
+obj\alpha\stubs.obj
+obj\alpha\jenstubs.obj
+obj\alpha\fwusa.obj
+obj\alpha\eisausa.obj
+obj\alpha\aha174x.obj
+..\..\..\bldr\obj\alpha\fatboot.obj
+..\..\..\bldr\obj\alpha\ntfsboot.obj
+..\..\..\bldr\obj\alpha\cdfsboot.obj
+..\..\..\bldr\obj\alpha\scsiboot.obj
+..\..\..\bldr\obj\alpha\scsidisk.obj
+..\..\..\rtl\obj\alpha\rtl.lib
+..\..\..\nthals\hal0jens\obj\alpha\axlbsup.obj
+..\..\..\nthals\hal0jens\obj\alpha\halpal.obj
+..\..\..\nthals\hal0jens\obj\alpha\jxcache.obj
+..\..\..\nthals\hal0jens\obj\alpha\jxioacc.obj
+..\..\..\nthals\hal0jens\obj\alpha\jxtime.obj
+..\..\..\nthals\hal0jens\obj\alpha\jxvtisup.obj
+\nt\public\sdk\lib\alpha\libcnt.lib
diff --git a/private/ntos/fw/alpha/jensen/linkupd.rsp b/private/ntos/fw/alpha/jensen/linkupd.rsp
new file mode 100644
index 000000000..77c585881
--- /dev/null
+++ b/private/ntos/fw/alpha/jensen/linkupd.rsp
@@ -0,0 +1,21 @@
+-machine:alpha
+-rom
+-fixed
+-base:0x80080000
+-align:0x100
+-debug:full
+-debugtype:coff
+-entry:main
+obj\alpha\jnupdate.obj
+obj\alpha\version.obj
+obj\alpha\ujnsetcm.obj
+obj\alpha\rom.obj
+obj\alpha\jnupass.obj
+obj\alpha\jnupstub.obj
+obj\alpha\ustubs.obj
+obj\alpha\jenstubs.obj
+obj\alpha\fwusa.obj
+obj\alpha\fwchkstk.obj
+..\..\..\nthals\hal0jens\obj\alpha\jxioacc.obj
+..\..\..\rtl\obj\alpha\rtl.lib
+\nt\public\sdk\lib\alpha\libcnt.lib
diff --git a/private/ntos/fw/alpha/jensen/makefile b/private/ntos/fw/alpha/jensen/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/fw/alpha/jensen/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/fw/alpha/jensen/makefile.inc b/private/ntos/fw/alpha/jensen/makefile.inc
new file mode 100644
index 000000000..56d90a7da
--- /dev/null
+++ b/private/ntos/fw/alpha/jensen/makefile.inc
@@ -0,0 +1,423 @@
+!IF $(ALPHA)
+
+#
+# NT/Alpha AXP Firmware
+#
+
+alpha\palcode\fw: obj\alpha\jensfw.exe \
+ alpha\palcode\fwimagen.exe \
+ alpha\palcode\fwpack.exe \
+ alpha\palcode\fwpal.nh
+ anm obj\alpha\jensfw.exe > obj\alpha\jensfw.sym
+ strip -m -s 80704000 -o obj\alpha\jensfw.str obj\alpha\jensfw.exe
+ cd alpha\palcode
+ fwimagen fwpal.nh ..\..\obj\alpha\jensfw.str fw
+ cd ..\..
+
+#
+# These are the inference and dependency rules for making a
+# copy of a file from the common area to the platform build area so
+# it can be compiled.
+#
+# Because of a deficiency in nmake, the inference rules do not work
+# if the target file (the copy in jensen\alpha) does not already exist.
+# As a remedy, there are null explicit dependency rules for each
+# local target of a common file.
+#
+# The copies are made readonly to reduce the
+# likelyhood of accidently editing the copy instead of the original
+# in the common area.
+#
+
+alpha\bldrstub.c:
+
+alpha\conftest.c:
+
+alpha\eisafunc.c:
+
+alpha\eisaini.c:
+
+alpha\eisamisc.c:
+
+alpha\eisapod.c:
+
+alpha\eisausa.c:
+
+alpha\fakebldr.c:
+
+alpha\fwchkstk.s:
+
+alpha\fwkd.c:
+
+alpha\fwhalt.c:
+
+alpha\fwio.c:
+
+alpha\fwload.c:
+
+alpha\fwprint.c:
+
+alpha\fwrstb.c:
+
+alpha\fwsignal.c:
+
+alpha\fwtime.c:
+
+alpha\fwupusa.c:
+
+alpha\fwusa.c:
+
+alpha\jenassem.s:
+
+alpha\jenfonts.c:
+
+alpha\jnfsinit.c:
+
+alpha\jnfsstb.c:
+
+alpha\jnfsstub.s:
+
+alpha\jnsetcom.c:
+
+alpha\jnsetenv.c:
+
+alpha\jnsetmak.c:
+
+alpha\jnsetset.c:
+
+alpha\jnsettim.c:
+
+alpha\jnupass.s:
+
+alpha\jnupdate.c:
+
+alpha\jnupstub.c:
+
+alpha\jxboot.c:
+
+alpha\jxconfig.c:
+
+alpha\jxdisp.c:
+
+alpha\jxenvir.c:
+
+alpha\jxfboot.c:
+
+alpha\jxhwsup.c:
+
+alpha\jxkbd.c:
+
+alpha\jxreboot.c:
+
+alpha\jxserial.c:
+
+alpha\jxsysid.c:
+
+alpha\jxvendor.c:
+
+alpha\kbdtest.c:
+
+alpha\kdstubs.c:
+
+alpha\monitor.c:
+
+alpha\omf.c:
+
+alpha\rom.c:
+
+alpha\stubs.c:
+
+{..}.s{alpha}.s:
+ attrib -r $@ > nul 2>&1
+ copy $** $@
+ attrib +r $@
+
+{..}.c{alpha}.c:
+ attrib -r $@ > nul 2>&1
+ copy $** $@
+ attrib +r $@
+
+
+
+obj\alpha\jensfw.exe: obj\alpha\selftest.obj \
+ obj\alpha\jenstubs.obj \
+ obj\alpha\eisafunc.obj \
+ obj\alpha\aha174x.obj \
+ obj\alpha\eisaini.obj \
+ obj\alpha\fwkd.obj \
+ obj\alpha\kdstubs.obj \
+ obj\alpha\bldrstub.obj \
+ obj\alpha\fwusa.obj \
+ obj\alpha\eisausa.obj \
+ obj\alpha\eisamisc.obj \
+ obj\alpha\eisapod.obj \
+ obj\alpha\fwio.obj \
+ obj\alpha\fwchkstk.obj \
+ obj\alpha\fwload.obj \
+ obj\alpha\fwprint.obj \
+ obj\alpha\fwhalt.obj \
+ obj\alpha\fwrstb.obj \
+ obj\alpha\fwsignal.obj \
+ obj\alpha\xxstring.obj \
+ obj\alpha\fwtime.obj \
+ obj\alpha\jenassem.obj \
+ obj\alpha\jenfonts.obj \
+ obj\alpha\jnsetcfg.obj \
+ obj\alpha\jnsetcom.obj \
+ obj\alpha\jnsetenv.obj \
+ obj\alpha\jnsetmak.obj \
+ obj\alpha\jnsetset.obj \
+ obj\alpha\jnsettim.obj \
+ obj\alpha\jxboot.obj \
+ obj\alpha\jxconfig.obj \
+ obj\alpha\jxdisp.obj \
+ obj\alpha\jxenvir.obj \
+ obj\alpha\jxfboot.obj \
+ obj\alpha\jxhwsup.obj \
+ obj\alpha\jxkbd.obj \
+ obj\alpha\jxmemory.obj \
+ obj\alpha\jxreboot.obj \
+ obj\alpha\jxserial.obj \
+ obj\alpha\jxsysid.obj \
+ obj\alpha\jxvendor.obj \
+ obj\alpha\kbdtest.obj \
+ obj\alpha\monitor.obj \
+ obj\alpha\rom.obj \
+ obj\alpha\omf.obj \
+ obj\alpha\stubs.obj \
+ obj\alpha\tbaqva.obj \
+ .\linkjens.rsp
+ link -machine:alpha -out:obj\alpha\jensfw.exe @linkjens.rsp
+
+
+
+
+#
+# FailSafe Booter
+#
+
+alpha\palcode\fsb: obj\alpha\fsb.exe \
+ alpha\palcode\fwimagen.exe \
+ alpha\palcode\fwpack.exe \
+ alpha\palcode\fwpal.nh
+ anm obj\alpha\fsb.exe > obj\alpha\fsb.sym
+ strip -m -s 80704000 -o obj\alpha\fsb.str obj\alpha\fsb.exe
+ cd alpha\palcode
+ fwimagen fwpal.nh ..\..\obj\alpha\fsb.str fsb
+ cd ..\..
+
+obj\alpha\fsb.exe: obj\alpha\jnfs.obj \
+ obj\alpha\fwusa.obj \
+ obj\alpha\aha174x.obj \
+ obj\alpha\jnfsinit.obj \
+ obj\alpha\fwchkstk.obj \
+ obj\alpha\jenstubs.obj \
+ obj\alpha\ffwio.obj \
+ obj\alpha\fwprint.obj \
+ obj\alpha\xxstring.obj \
+ obj\alpha\fjenfont.obj \
+ obj\alpha\fjnsetcm.obj \
+ obj\alpha\fjxdisp.obj \
+ obj\alpha\fjxconfg.obj \
+ obj\alpha\fjxvendr.obj \
+ obj\alpha\jnfsstub.obj \
+ obj\alpha\jnfsstb.obj \
+ obj\alpha\fwload.obj \
+ obj\alpha\jxmemory.obj \
+ obj\alpha\jxhwsup.obj \
+ obj\alpha\jxkbd.obj \
+ obj\alpha\jxfboot.obj \
+ obj\alpha\fwtime.obj \
+ obj\alpha\fwsignal.obj \
+ obj\alpha\kbdtest.obj \
+ obj\alpha\fstubs.obj \
+ obj\alpha\tbaqva.obj \
+ obj\alpha\version.obj \
+ .\linkfsb.rsp
+ link -machine:alpha -out:obj\alpha\fsb.exe @linkfsb.rsp
+
+
+
+obj\alpha\ffwio.obj: alpha\ffwio.c
+
+obj\alpha\fjenfont.obj: alpha\fjenfont.c
+
+obj\alpha\fjnsetcm.obj: alpha\fjnsetcm.c
+
+obj\alpha\fjxconfg.obj: alpha\fjxconfg.c
+
+obj\alpha\fjxdisp.obj: alpha\fjxdisp.c
+
+obj\alpha\fjxvendr.obj: alpha\fjxvendr.c
+
+obj\alpha\fstubs.obj: alpha\fstubs.c
+
+alpha\fjenfont.c: ..\jenfonts.c
+ attrib -r $@ > nul 2>&1
+ copy ..\jnfsfsb.h+$** $@
+ attrib +r $@
+
+
+alpha\fjnsetcm.c: ..\jnsetcom.c
+ attrib -r $@ > nul 2>&1
+ copy ..\jnfsfsb.h+$** $@
+ attrib +r $@
+
+
+alpha\ffwio.c: ..\fwio.c
+ attrib -r $@ > nul 2>&1
+ copy ..\jnfsfsb.h+$** $@
+ attrib +r $@
+
+
+alpha\fjxconfg.c: ..\jxconfig.c
+ attrib -r $@ > nul 2>&1
+ copy ..\jnfsfsb.h+$** $@
+ attrib +r $@
+
+alpha\fjxdisp.c: ..\jxdisp.c
+ attrib -r $@ > nul 2>&1
+ copy ..\jnfsfsb.h+$** $@
+ attrib +r $@
+
+
+alpha\fjxvendr.c: ..\jxvendor.c
+ attrib -r $@ > nul 2>&1
+ copy ..\jnfsfsb.h+$** $@
+ attrib +r $@
+
+
+alpha\fstubs.c: ..\stubs.c
+ attrib -r $@ > nul 2>&1
+ copy ..\jnfsfsb.h+$** $@
+ attrib +r $@
+
+
+
+
+
+
+#
+# Jensen firmware update program
+#
+
+obj\alpha\jnupdate.exe: obj\alpha\jnupdate.obj \
+ obj\alpha\ujnsetcm.obj \
+ obj\alpha\rom.obj \
+ obj\alpha\jnupass.obj \
+ obj\alpha\jnupstub.obj \
+ obj\alpha\ustubs.obj \
+ obj\alpha\fwupusa.obj \
+ obj\alpha\jenstubs.obj \
+ obj\alpha\version.obj \
+ obj\alpha\fwchkstk.obj \
+ .\linkupd.rsp
+ link -machine:alpha -out:obj\alpha\jnupdate.exe @linkupd.rsp
+ anm obj\alpha\jnupdate.exe > obj\alpha\jnupdate.sym
+
+obj\alpha\ujnsetcm.obj: alpha\ujnsetcm.c
+
+obj\alpha\ustubs.obj: alpha\ustubs.c
+
+alpha\ujnsetcm.c: ..\jnsetcom.c
+ attrib -r $@ > nul 2>&1
+ copy ..\jnupdate.h+$** $@
+ attrib +r $@
+
+
+alpha\ustubs.c: ..\stubs.c
+ attrib -r $@ > nul 2>&1
+ copy ..\jnupdate.h+$** $@
+ attrib +r $@
+
+
+
+
+#
+# Alpha configuration and memory descriptor diagnostic
+#
+
+obj\alpha\conftest.exe: obj\alpha\conftest.obj \
+ obj\alpha\xxstring.obj \
+ ..\conftest.rsp
+ link -machine:alpha -out:obj\alpha\conftest.exe @..\conftest.rsp
+ anm obj\alpha\conftest.exe > obj\alpha\conftest.sym
+
+
+
+
+
+
+#
+# Alpha osloader diagnostic
+#
+
+obj\alpha\fakebldr.exe: obj\alpha\fakebldr.obj \
+ ..\fakebldr.rsp
+ link -machine:alpha -out:obj\alpha\fakebldr.exe @..\fakebldr.rsp
+ anm obj\alpha\fakebldr.exe > obj\alpha\fakebldr.sym
+
+
+
+
+
+
+
+#
+# PALcode concatenation tool
+#
+# This is executed on host development machine.
+#
+# PALCODEINC and PALCODELIB must be changed to point at their respective
+# sdk areas on the host machine.
+#
+
+PALCODEINC=d:\nt501\nt\public\sdk\inc\crt
+PALCODELIB=d:\nt501\nt\public\sdk\lib\alpha
+
+alpha\palcode\fwimagen.exe: ..\tools\fwimagen\fwimagen.c
+ copy ..\tools\fwimagen\fwimagen.c alpha\palcode\fwimagen.c
+ cd alpha\palcode
+ acc -I$(PALCODEINC) -o fwimagen.o fwimagen.c
+ a2coff fwimagen.o
+ link -out:fwimagen.exe -subsystem:console -entry:mainCRTStartup \
+ fwimagen.o $(PALCODELIB)\kernel32.lib $(PALCODELIB)\libcmt.lib $(PALCODELIB)\ntdll.lib
+ cd ..\..
+
+
+
+#
+# Alpha/Jensen Firmware update file (JENSFW.BIN) creation tool
+# This is executed on host development machine.
+#
+
+FWPACKINC=d:\nt501\nt\public\sdk\inc\crt
+FWPACKLIB=d:\nt501\nt\public\sdk\lib\alpha
+
+alpha\palcode\fwpack.exe: ..\tools\fwpack\fwpack.c
+ copy ..\tools\fwpack\fwpack.c alpha\palcode\fwpack.c
+ cd alpha\palcode
+ acc -I$(FWPACKINC) -o fwpack.o fwpack.c
+ a2coff fwpack.o
+ link -out:fwpack.exe -subsystem:console -entry:mainCRTStartup \
+ fwpack.o $(FWPACKLIB)\kernel32.lib $(FWPACKLIB)\libcmt.lib $(FWPACKLIB)\ntdll.lib
+ cd ..\..
+
+
+
+#
+# A hacked version of fwpack that is used for testing the FailSafe Booter
+# code.
+#
+
+alpha\palcode\fsbpack.exe: ..\tools\fwpack\fsbpack.c
+ copy ..\tools\fwpack\fsbpack.c alpha\palcode\fsbpack.c
+ cd alpha\palcode
+ acc -I$(FWPACKINC) -o fsbpack.o fsbpack.c
+ a2coff fsbpack.o
+ link -out:fsbpack.exe -subsystem:console -entry:mainCRTStartup \
+ fsbpack.o $(FWPACKLIB)\kernel32.lib $(FWPACKLIB)\libcmt.lib $(FWPACKLIB)\ntdll.lib
+ cd ..\..
+
+
+!ENDIF
diff --git a/private/ntos/fw/alpha/jensen/readmekd.txt b/private/ntos/fw/alpha/jensen/readmekd.txt
new file mode 100644
index 000000000..485155f7e
--- /dev/null
+++ b/private/ntos/fw/alpha/jensen/readmekd.txt
@@ -0,0 +1,68 @@
+Building the kernel debugger into the NT/Jensen firmware
+--------------------------------------------------------
+
+John DeRosa 4/14/93
+
+
+It would be nice if we could always include the kernel debugger stub,
+or if it could be included by simply turning on a compile switch.
+Unfortunately, the kd stub amounts to over 30kb of code, and there
+isn't enough remaining ROM space for it. This number could be reduced
+by a smarter treatment of library functions, but such an effort hasn't
+yet been done.
+
+Also, the kernel debugger cannot read a "-rom" linked jensfw.exe image.
+
+So, for the time being, this is how to link the kernel debugger stub
+into the firmware:
+
+1. Make space for the debugger stub by not linking in some code. Easy
+targets are NTFS, CDFS, or EISA bus configuration. Currently the
+code is set up for the victim to be the NTFS filesystem.
+
+2. Edit linkjens.rsp to remove the modules from (#1) from the link list.
+
+3. Add these lines to linkjens.rsp:
+
+ obj\alpha\fwkd.obj
+ obj\alpha\kdstubs.obj
+ ..\..\..\nthals\hal0jens\obj\alpha\jxport.obj
+
+4. Add this line to the end of linkjens.rsp:
+
+ \nt\private\ntos\obj\alpha\kd.lib
+
+5. Copy linkjens.rsp to linkjens.tru.
+ Copy linkjens.rsp to linkjens.dbg.
+
+6. Edit linkjens.dbg and remove these switches:
+
+ -rom
+ -fixed
+
+7. Edit sources and turn on the ALPHA_FW_KDHOOKS switch.
+
+8. Delete all .obj files from jensen\obj\alpha which will be affected by
+ALPHA_FW_KDHOOKS.
+
+9. build.
+
+10. Create jensfw.bin.
+
+11. Additional steps must be followed for symbolic debugging. This is
+because the kernel debugger is unable to read the "-rom" linked
+jensfw.exe:
+
+ a. Copy linkjens.dbg to linkjens.rsp.
+
+ b. del obj\alpha\jensfw.exe
+
+ c. build
+
+ d. jensen\obj\alpha\jensfw.exe is now suitable for alphakd.
+
+ e. To run alphakd:
+
+ set _NT_SYMBOL_PATH=\nt\private\ntos\fw\alpha\jensen\obj\alpha
+ cd obj\alpha
+ alphakd
diff --git a/private/ntos/fw/alpha/jensen/sources b/private/ntos/fw/alpha/jensen/sources
new file mode 100644
index 000000000..d644f8759
--- /dev/null
+++ b/private/ntos/fw/alpha/jensen/sources
@@ -0,0 +1,220 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+ N.B. This file is for Alpha/Jensen (DECpc AXP 150) builds only.
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+
+
+Revision History:
+
+ John DeRosa [DEC] 23-June-1992
+
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=fw
+
+TARGETNAME=fw
+TARGETPATH=obj
+TARGETTYPE=LIBRARY
+
+ALPHA_OPTIONS= -checkstack 16 -DEISA_PLATFORM
+
+C_DEFINES = -DJENSEN
+
+!IF $(ALPHA)
+INCLUDES=.\alpha;..;..\..\..\inc;..\..\..\fastfat;..\..\..\bldr;..\..\..\nthals\hal0jens\alpha;..\..\..\bldr\alpha;..\..\..\dd\floppy;..\..\..\miniport\aha174x
+!ENDIF
+
+SOURCES=
+
+
+!IF 0
+Alpha AXP switches:
+
+OMF_DEBUG: set to TRUE when debugging the EISA functions.
+
+ALPHA_FW_SERDEB: define to build in the serial port debug print function.
+
+ALPHA_FW_VDB: define to build in video debugging.
+
+ALPHA_FW_KDHOOKS: define to build in KD stub. See fw\alpha\readmekd.txt.
+Put this in to use the kernel debugger.
+
+Define JENSEN for a Jensen build.
+
+Define MORGAN for a Morgan build.
+
+Define EISA_PLATFORM for an EISA machine. Such a machine will have an
+EISA configuration utility that will configure the CDS tree.
+
+Define ISA_PLATFORM for an ISA machine.
+
+Other notes:
+
+checkstack needs to be a low value so that the firmware, FailSafe Booter,
+and JNUPDATE.EXE do run-time stack checking for all function calls.
+It doesn't need to be a low value for the other programs but the
+performance impact on them isn't enough to warrant changing the build
+procedure.
+
+Eg:
+
+ ALPHA_OPTIONS=-checkstack 16 -DALPHA_FW_KDHOOKS -DEISA_PLATFORM
+
+!ENDIF
+
+ALPHA_SOURCES=alpha\fwio.c \
+ alpha\tbaqva.c \
+ alpha\aha174x.c \
+ alpha\fwchkstk.s \
+ alpha\fwkd.c \
+ alpha\bldrstub.c \
+ alpha\kdstubs.c \
+ alpha\fwhalt.c \
+ alpha\fwload.c \
+ alpha\fwprint.c \
+ alpha\fwsignal.c \
+ alpha\fwrstb.c \
+ alpha\fwtime.c \
+ alpha\jenassem.s \
+ alpha\jenfonts.c \
+ alpha\jnsetcfg.c \
+ alpha\jnsetcom.c \
+ alpha\jnsetenv.c \
+ alpha\jnsetmak.c \
+ alpha\jnsetset.c \
+ alpha\jnsettim.c \
+ alpha\jxboot.c \
+ alpha\jxconfig.c \
+ alpha\jxdisp.c \
+ alpha\jxenvir.c \
+ alpha\jxfboot.c \
+ alpha\jxhwsup.c \
+ alpha\jxkbd.c \
+ alpha\jxmemory.c \
+ alpha\jxreboot.c \
+ alpha\jxserial.c \
+ alpha\jxsysid.c \
+ alpha\jxvendor.c \
+ alpha\kbdtest.c \
+ alpha\monitor.c \
+ alpha\omf.c \
+ alpha\selftest.c \
+ alpha\jenstubs.c \
+ alpha\stubs.c \
+ alpha\eisafunc.c \
+ alpha\eisaini.c \
+ alpha\eisamisc.c \
+ alpha\eisapod.c \
+ alpha\conftest.c \
+ alpha\fakebldr.c \
+ alpha\jnfs.c \
+ alpha\jnfsinit.c \
+ alpha\jnfsstub.s \
+ alpha\fjenfont.c \
+ alpha\ffwio.c \
+ alpha\fjxconfg.c \
+ alpha\fjxdisp.c \
+ alpha\fjxvendr.c \
+ alpha\fjnsetcm.c \
+ alpha\fstubs.c \
+ alpha\ustubs.c \
+ alpha\ujnsetcm.c \
+ alpha\jnupdate.c \
+ alpha\jnupass.s \
+ alpha\jnupstub.c \
+ alpha\jnfsstb.c \
+ alpha\fwupusa.c \
+ alpha\fwusa.c \
+ alpha\xxstring.c \
+ alpha\eisausa.c \
+ alpha\rom.c \
+ alpha\version.c
+
+
+
+!IF $(ALPHA)
+
+!IF $(JENSEN)
+
+NTTARGETFILES=alpha\bldrstub.c \
+ alpha\eisafunc.c \
+ alpha\eisaini.c \
+ alpha\eisamisc.c \
+ alpha\eisapod.c \
+ alpha\eisausa.c \
+ alpha\fakebldr.c \
+ alpha\fwchkstk.s \
+ alpha\fwhalt.c \
+ alpha\fwio.c \
+ alpha\fwkd.c \
+ alpha\fwload.c \
+ alpha\fwprint.c \
+ alpha\fwrstb.c \
+ alpha\fwsignal.c \
+ alpha\fwtime.c \
+ alpha\fwupusa.c \
+ alpha\fwusa.c \
+ alpha\jenassem.s \
+ alpha\jenfonts.c \
+ alpha\jnfs.c \
+ alpha\jnfsinit.c \
+ alpha\jnfsstb.c \
+ alpha\jnfsstub.s \
+ alpha\jnsetcfg.c \
+ alpha\jnsetcom.c \
+ alpha\jnsetenv.c \
+ alpha\jnsetmak.c \
+ alpha\jnsetset.c \
+ alpha\jnsettim.c \
+ alpha\jnupass.s \
+ alpha\jnupdate.c \
+ alpha\jnupstub.c \
+ alpha\jxboot.c \
+ alpha\jxconfig.c \
+ alpha\jxdisp.c \
+ alpha\jxenvir.c \
+ alpha\jxfboot.c \
+ alpha\jxhwsup.c \
+ alpha\jxkbd.c \
+ alpha\jxreboot.c \
+ alpha\jxserial.c \
+ alpha\jxsysid.c \
+ alpha\jxvendor.c \
+ alpha\kbdtest.c \
+ alpha\kdstubs.c \
+ alpha\monitor.c \
+ alpha\omf.c \
+ alpha\rom.c \
+ alpha\selftest.c \
+ alpha\stubs.c \
+ obj\alpha\jnupdate.exe \
+ obj\alpha\conftest.exe \
+ obj\alpha\fakebldr.exe \
+ alpha\palcode\fw \
+ alpha\palcode\fsb \
+ alpha\palcode\fsbpack.exe
+
+!ENDIF
+
+!ENDIF
diff --git a/private/ntos/fw/alpha/jnfs.h b/private/ntos/fw/alpha/jnfs.h
new file mode 100644
index 000000000..0dd910624
--- /dev/null
+++ b/private/ntos/fw/alpha/jnfs.h
@@ -0,0 +1,84 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ jnfs.h
+
+Abstract:
+
+ This contains firmware update related definitions for the FailSafe Booter
+ and JNUPDATE.EXE.
+
+Author:
+
+ John DeRosa 20-October-1992
+
+Revision History:
+
+
+--*/
+
+#ifndef _JNFS_
+#define _JNFS_
+
+
+//
+// Check for correct compilation
+//
+
+#if defined(FAILSAFE_BOOTER) && defined(JNUPDATE)
+#error ??!!?? FAILSAFE_BOOTER and JNUPDATE are both defined ??!!??
+#endif
+
+
+
+//
+// Function prototypes
+//
+
+ARC_STATUS
+JnFsStoreIntoROM(
+ IN PUCHAR FirmwareStart,
+ IN ULONG LowROMBlock,
+ IN ULONG HighROMBlock
+ );
+
+BOOLEAN
+AllBlocksNotDone (
+ IN PBOOLEAN StatusArray,
+ IN ULONG StartIndex,
+ IN ULONG EndIndex
+ );
+
+ARC_STATUS
+ReadAndVerifyUpdateFile(
+ IN PCHAR PathName,
+ OUT PULONG BufferAddress,
+ OUT PULONG FirmwareStart,
+ OUT PULONG BufferLength,
+ OUT PULONG LowROMBlock,
+ OUT PULONG HighROMBlock
+ );
+
+ARC_STATUS
+JnFsAllocateDescriptor(
+ IN ULONG MemoryType,
+ IN ULONG PageCount,
+ OUT PULONG ActualBase
+ );
+
+BOOLEAN
+JnFsProceedWithUpdate (
+ VOID
+ );
+
+VOID
+JnFsDecodeBadStatus (
+ IN ARC_STATUS Status
+ );
+
+
+
+#endif // _JNFS_
diff --git a/private/ntos/fw/alpha/jnfsfsb.h b/private/ntos/fw/alpha/jnfsfsb.h
new file mode 100644
index 000000000..b7ce16e84
--- /dev/null
+++ b/private/ntos/fw/alpha/jnfsfsb.h
@@ -0,0 +1 @@
+#define FAILSAFE_BOOTER 1
diff --git a/private/ntos/fw/alpha/jnfsinit.c b/private/ntos/fw/alpha/jnfsinit.c
new file mode 100644
index 000000000..9e6680393
--- /dev/null
+++ b/private/ntos/fw/alpha/jnfsinit.c
@@ -0,0 +1,294 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ jnfsinit.c
+
+Abstract:
+
+ This module implements the main part of the FailSafe Booter. It was
+ based on jxboot.c.
+
+Author:
+
+ John DeRosa 21-October-1992
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "fwp.h"
+
+#ifdef JENSEN
+#include "jnsnrtc.h"
+#else
+#include "mrgnrtc.h" // morgan
+#endif
+
+#include "string.h"
+#include "led.h"
+#include "fwstring.h"
+#include "xxstring.h"
+
+extern PCHAR FirmwareVersion;
+
+//
+// Define local procedure prototypes.
+//
+
+typedef
+VOID
+(*PTRANSFER_ROUTINE) (
+ IN ULONG Argc,
+ IN PCHAR Argv[],
+ IN PCHAR Envp[]
+ );
+
+VOID
+PutLedDisplay(
+ IN UCHAR Value
+ );
+
+
+//
+// Saved sp
+//
+
+ULONG FwSavedSp;
+
+
+VOID
+JnFsUpgradeSystem (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine attempts to load the upgrade image into memory.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ARC_STATUS Status;
+
+ //
+ // Initialize value for the ALIGN_BUFFER macro.
+ //
+
+ BlDcacheFillSize = KeGetDcacheFillSize();
+
+ //
+ // Initialize the firmware servies.
+ //
+
+ FwInitialize(0);
+
+ FwSetScreenColor( ArcColorWhite, ArcColorBlue);
+ FwSetScreenAttributes( TRUE, FALSE, FALSE);
+ FwClearScreen();
+ FwSetPosition(1,0);
+
+ PutLedDisplay(LED_FW_INITIALIZED);
+
+ FwPrint(FSB_MSG, FirmwareVersion);
+ FwPrint(FW_COPYRIGHT_MSG);
+ FwPrint(FSB_WHY_RUNNING_MSG);
+ FwSetScreenAttributes( FALSE, FALSE, FALSE);
+ FwSetScreenColor(ArcColorRed, ArcColorWhite);
+ FwPrint(FSB_FIELD_SERVICE_MSG);
+ FwSetScreenAttributes( TRUE, FALSE, FALSE);
+ FwSetScreenColor( ArcColorWhite, ArcColorBlue);
+
+ FwPrint(FSB_LOOKING_FOR_MSG);
+
+ FwSavedSp = 0;
+
+ Status = FwExecute("eisa()disk()fdisk()jnupdate.exe", 0, NULL, NULL);
+
+ if (Status != ESUCCESS) {
+
+ FwSetScreenAttributes( FALSE, FALSE, FALSE);
+ FwSetScreenColor(ArcColorRed, ArcColorWhite);
+ FwPrint(FW_ERROR2_MSG);
+
+ if (Status <= EROFS) {
+ FwPrint(FW_ERROR_MSG[Status - 1]);
+ } else {
+ FwPrint(FW_ERROR_CODE_MSG, Status);
+ }
+
+ FwPrint(FSB_UPGRADE_ABORTED_MSG);
+ }
+
+ //
+ // No matter how we returned, hang if we come back.
+ //
+
+ VenPrint(FSB_POWER_CYCLE_TO_REBOOT_MSG);
+
+ while (TRUE) {
+ }
+}
+
+VOID
+FwInitialize (
+ IN ULONG MemSize
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the system parameter block which is located
+ in low memory. This structure contains the firmware entry vector and
+ the restart parameter block. This routine also initializes the io devices,
+ the configuration, and opens standard in/out.
+
+Arguments:
+
+ MemSize - Not Used. For compatibility with definitions in bldr\firmware.h
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG Fid;
+ ULONG TTBase;
+ PCHAR ConsoleName;
+ ULONG Index;
+ CHAR DiskPath[40];
+
+ //
+ // Initialize Vendor Must be done before Calling FwAllocatePool. Also
+ // initialize the system ID and time.
+ //
+
+ FwVendorInitialize();
+ //FwSystemIdInitialize();
+ FwTimeInitialize();
+
+ //
+ // Initialize the Fw loadable services.
+ //
+ FwLoadInitialize();
+
+
+ //
+ // Initialize the termination function entry points in the transfer vector
+ //
+ //FwTerminationInitialize();
+
+
+ //
+ // Initialize configuration
+ //
+
+ FwConfigurationInitialize();
+
+ //
+ // Initialize IO structures and display driver.
+ //
+
+ FwIoInitialize1();
+
+ //
+ // Initialize the I/O services and environment.
+ //
+
+ FwIoInitialize2();
+ //FwEnvironmentInitialize();
+
+ //
+ // Open the std in and out device.
+ //
+
+ FwOpenConsole();
+ FwConsoleInitialized = TRUE;
+
+ //
+ // Spinning up the disks and initting the Eisa routines are not necessary.
+ //
+
+ return;
+}
+
+VOID
+FwOpenConsole(
+ IN VOID
+ )
+/*++
+
+Routine Description:
+
+ This opens the console input and output devices. This does not
+ reference the environment variables, as we do not have full
+ environment variable support to minimize code space.
+
+Arguments:
+
+ None.
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG Fid;
+ PCHAR ConsoleName;
+
+ //
+ // Open the std in and out device.
+ //
+
+ if (SerialOutput) {
+ ConsoleName=FW_SERIAL_0_DEVICE;
+ } else {
+ ConsoleName=FW_KEYBOARD_IN_DEVICE;
+ }
+
+ if (FwOpen(ConsoleName,ArcOpenReadOnly,&Fid) != ESUCCESS) {
+ FwPrint(FW_CONSOLE_IN_ERROR_MSG);
+ FwPrint(FW_CONTACT_FIELD_SERVICE_MSG);
+ }
+
+ if (Fid != ARC_CONSOLE_INPUT) {
+ FwPrint(FW_CONSOLE_IN_ERROR2_MSG);
+ }
+
+ if (SerialOutput) {
+ ConsoleName=FW_SERIAL_0_DEVICE;
+ } else {
+ ConsoleName=FW_CONSOLE_OUT_DEVICE;
+ }
+
+ if (FwOpen(ConsoleName,ArcOpenWriteOnly,&Fid) != ESUCCESS) {
+ FwPrint(FW_CONSOLE_OUT_ERROR_MSG);
+ FwPrint(FW_CONTACT_FIELD_SERVICE_MSG);
+ }
+
+ if (Fid != ARC_CONSOLE_OUTPUT) {
+ FwPrint(FW_CONSOLE_OUT_ERROR2_MSG);
+ }
+}
diff --git a/private/ntos/fw/alpha/jnfsstb.c b/private/ntos/fw/alpha/jnfsstb.c
new file mode 100644
index 000000000..4cf40edea
--- /dev/null
+++ b/private/ntos/fw/alpha/jnfsstb.c
@@ -0,0 +1,335 @@
+/*++
+
+Module Name:
+
+ jnfsstb.c
+
+Abstract:
+
+ \nt\private\ntos\bldr\alpha\stubs.c variant stub functions for
+ the FailSafe Booter.
+
+Author:
+
+ John DeRosa 20-Oct-1992
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "fwp.h"
+#include "fwstring.h"
+
+//
+// Define global data.
+//
+
+ULONG BlDcacheFillSize = 32;
+
+VOID
+KeBugCheck (
+ IN ULONG BugCheckCode
+ )
+
+/*++
+
+Routine Description:
+
+ This function crashes the system in a controlled manner.
+
+ Alpha/Jensen firmware will try to run the Monitor instead of the
+ kernel debugger.
+
+Arguments:
+
+ BugCheckCode - Supplies the reason for the bug check.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+#ifdef JENSEN
+
+ //
+ // Print out the bug check code and halt.
+ //
+
+ VenPrint1(ST_BUGCHECK_MSG, BugCheckCode);
+ VenPrint(ST_HIT_KEY_FOR_REBOOT_MSG);
+ FwWaitForKeypress(FALSE);
+ AlphaInstHalt();
+
+#else
+
+ //
+ // Print out the bug check code and break.
+ //
+
+ DbgPrint(ST_BUGCHECK_MSG, BugCheckCode);
+ while(TRUE) {
+ DbgBreakPoint();
+ };
+
+#endif
+
+ return;
+}
+
+LARGE_INTEGER
+KeQueryPerformanceCounter (
+ OUT PLARGE_INTEGER Frequency OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is a stub for the kernel debugger and always returns a
+ value of zero.
+
+Arguments:
+
+ Frequency - Supplies an optional pointer to a variable which receives
+ the performance counter frequency in Hertz.
+
+Return Value:
+
+ A value of zero is returned.
+
+--*/
+
+{
+
+ LARGE_INTEGER Counter;
+
+ //
+ // Return the current system time as the function value.
+ //
+
+ Counter.LowPart = 0;
+ Counter.HighPart = 0;
+ return Counter;
+}
+
+VOID
+KeStallExecutionProcessor (
+ IN ULONG MicroSeconds
+ )
+
+/*++
+
+Routine Description:
+
+ This function stalls execution for the specified number of microseconds.
+
+Arguments:
+
+ MicroSeconds - Supplies the number of microseconds that execution is to be
+ stalled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Index;
+ ULONG Limit;
+ PULONG Store;
+ ULONG Value;
+
+ //
+ // ****** begin temporary code ******
+ //
+ // This code must be replaced with a smarter version. For now it assumes
+ // an execution rate of 80,000,000 instructions per second and 4 instructions
+ // per iteration.
+ //
+
+ Store = &Value;
+ Limit = (MicroSeconds * 80 / 4);
+ for (Index = 0; Index < Limit; Index += 1) {
+ *Store = Index;
+ }
+ return;
+}
+
+BOOLEAN
+KeFreezeExecution (
+ IN PKTRAP_FRAME TrapFrame,
+ IN PEXCEPTION_RECORD ExceptionRecord
+ )
+
+/*++
+
+Routine Description:
+
+ This function freezes the execution of all other processors in the host
+ configuration and then returns to the caller. It is intended for use by
+ the kernel debugger.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Whether interrupts were previously enabled.
+
+--*/
+
+{
+
+ return FALSE;
+}
+
+VOID
+KeThawExecution (
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This function unfreezes the execution of all other processors in the host
+ configuration and then returns to the caller. It is intended for use by
+ the kernel debugger.
+
+Arguments:
+
+ Irql - Supplies the level that the IRQL is to be lowered to after having
+ unfrozen the execution of all other processors.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ return;
+}
+
+PVOID
+MmDbgReadCheck (
+ IN PVOID VirtualAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This routine returns the phyiscal address for a virtual address
+ which is valid (mapped) for read access.
+
+Arguments:
+
+ VirtualAddress - Supplies the virtual address to check.
+
+Return Value:
+
+ Returns NULL if the address is not valid or readable, otherwise
+ returns the physical address of the corresponding virtual address.
+
+--*/
+
+{
+
+ return VirtualAddress;
+}
+
+PVOID
+MmDbgTranslatePhysicalAddress (
+ IN PHYSICAL_ADDRESS PhysicalAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This routine returns the phyiscal address for a physical address
+ which is valid (mapped).
+
+Arguments:
+
+ PhysicalAddress - Supplies the physical address to check.
+
+Return Value:
+
+ Returns NULL if the address is not valid or readable, otherwise
+ returns the physical address of the corresponding virtual address.
+
+--*/
+
+{
+
+ return (PVOID)PhysicalAddress.LowPart;
+}
+
+PVOID
+MmDbgWriteCheck (
+ IN PVOID VirtualAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This routine returns the phyiscal address for a virtual address
+ which is valid (mapped) for write access.
+
+Arguments:
+
+ VirtualAddress - Supplies the virtual address to check.
+
+Return Value:
+
+ Returns NULL if the address is not valid or readable, otherwise
+ returns the physical address of the corresponding virtual address.
+
+--*/
+
+{
+ return VirtualAddress;
+}
+
+VOID
+RtlAssert(
+ IN PVOID FailedAssertion,
+ IN PVOID FileName,
+ IN ULONG LineNumber,
+ IN PCHAR Message OPTIONAL
+ )
+{
+
+#ifdef JENSEN
+
+ //
+ // Print out the assertion failure and go to the monitor.
+ //
+
+ VenPrint(ST_ASSERT_MSG);
+ AlphaInstHalt();
+
+#else
+
+ DbgPrint(ST_ASSERT_MSG);
+ while (TRUE) {
+ DbgBreakPoint();
+ }
+
+#endif
+
+}
diff --git a/private/ntos/fw/alpha/jnfsstub.s b/private/ntos/fw/alpha/jnfsstub.s
new file mode 100644
index 000000000..83203d5d9
--- /dev/null
+++ b/private/ntos/fw/alpha/jnfsstub.s
@@ -0,0 +1,353 @@
+#if defined(ALPHA)
+
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+
+Module Name:
+
+ jnfsstub.s
+
+
+Abstract:
+
+ A streamlined copy of jenassem.s, for the FailSafe Booter.
+
+Author:
+
+ John DeRosa 21-October-1992
+
+
+Environment:
+
+ Executes in kernel mode.
+
+Revision History:
+
+
+--*/
+
+
+#include "ksalpha.h"
+#include "selfmap.h"
+#include "jnsndef.h"
+
+/*****************************************************************
+
+Simple functions to perform PALcode calls and memory barriers.
+
+******************************************************************/
+
+
+ LEAF_ENTRY(AlphaInstIMB)
+
+ callpal imb
+ ret zero, (ra)
+
+ .end AlphaInstIMB
+
+
+
+ LEAF_ENTRY(AlphaInstMB)
+
+ mb
+ ret zero, (ra)
+
+ .end AlphaInstMB
+
+
+
+ LEAF_ENTRY(AlphaInstHalt)
+
+ callpal halt
+ ret zero, (ra) # should never return, but...
+
+ .end AlphaInstHalt
+
+
+
+#if 0
+ LEAF_ENTRY(DisableInterrupts)
+
+ callpal di
+ ret zero, (ra)
+
+ .end DisableInterrupts
+#endif
+
+
+
+ LEAF_ENTRY(RegisterExceptionHandler)
+
+ lda a0, FailSafeEntry # Restart main code on unexpected exceptions
+ callpal wrentry
+ ret zero, (ra)
+
+ .end RegisterExceptionHandler
+
+ NESTED_ENTRY(FwExecute, 0x60, ra)
+
+
+/*
+
+Routine Description:
+
+ This is the entry point for the Execute service.
+
+ It behaves in two different ways depending on where it is called from:
+
+ 1) If called from the Firmware, it saves the stack pointer
+ in a fixed location and then saves all the saved registers
+ in the stack. This is the stack that will be used to restore
+ the saved state when returning to the firmware.
+
+ 2) If called from a loaded program, the program to be loaded
+ and executed can overwrite the current program and its
+ stack. Therefore a temporary stack is set.
+
+Arguments:
+
+ a0 IN PCHAR Path,
+ a1 IN ULONG Argc,
+ a2 IN PCHAR Argv[],
+ a3 IN PCHAR Envp[]
+
+Return Value:
+
+ ARC_STATUS returned by FwPrivateExecute.
+ Always returns to the Firmware.
+
+ */
+
+ lda t0, FwSavedSp
+ subq sp, 0x60 # make room in the stack
+ stl sp, (t0) # save new stack pointer
+
+ stq ra, (sp) # return address on top of stack
+ stq s0, 0x8(sp) # save s registers
+ stq s1, 0x10(sp)
+ stq s2, 0x18(sp)
+ stq s3, 0x20(sp)
+ stq s4, 0x28(sp)
+ stq s5, 0x30(sp)
+ stq fp, 0x38(sp)
+ stq gp, 0x40(sp)
+ jsr ra, FwPrivateExecute # go do the work.
+
+RestoreFwState:
+ ldq ra, (sp) # restore return address
+ ldq s0, 0x8(sp) # restore s registers
+ ldq s1, 0x10(sp)
+ ldq s2, 0x18(sp)
+ ldq s3, 0x20(sp)
+ ldq s4, 0x28(sp)
+ ldq s5, 0x30(sp)
+ ldq fp, 0x48(sp)
+ ldq gp, 0x40(sp)
+ addq sp, 0x60 # restore stack pointer
+ ret zero, (ra) # return to firmware control
+
+ .end FwExecute
+
+ NESTED_ENTRY(FwInvoke, 0x40, ra)
+
+/*++
+ARC_STATUS
+FwInvoke(
+ IN ULONG ExecAddr,
+ IN ULONG StackAddr,
+ IN ULONG Argc,
+ IN PCHAR Argv[],
+ IN PCHAR Envp[]
+ )
+
+
+Routine Description:
+
+ This routine invokes a loaded program.
+
+Arguments:
+
+ ExecAddr - Supplies the address of the routine to call.
+
+ StackAddr - Supplies the address to which the stack pointer is set.
+
+ Argc, Argv, Envp - Supply the arguments and environment to pass to
+ Loaded program.
+
+ The stack pointer is saved in register s0 so that when the loaded
+ program returns, the old stack pointer can be restored.
+
+
+Return Value:
+
+ ESUCCESS is returned if the address is valid.
+ EFAULT indicates an invalid address.
+
+--*/
+
+
+ subq sp, 0x40 # make room on the stack
+ stq ra, (sp) # save ra on top of stack
+ stq s0, 0x8(sp) # save s0
+ and a0, 3, t1 # return EFAULT if unaligned address
+ ldiq v0, 0x6
+ bne zero, 1f # branch if address alignment error
+
+ mov a0, t12 # save program address in t12
+
+ mov sp, s0 # save stack pointer
+ mov a1, sp # ..and load new one for program
+ mov a2, a0 # argc becomes first argument
+ mov a3, a1 # argv becomes second argument
+ mov a4, a2 # envp becomes third argument
+
+ jsr ra, (t12) # call program
+
+ // here if loaded program returns.
+
+ mov s0, sp # restore stack pointer
+ mov zero, v0 # return ESUCCESS value
+ ldq s0, 0x8(sp) # restore things
+ ldq ra, (sp)
+1:
+ addq sp, 0x40
+ ret zero, (ra)
+
+ .end FwInvoke
+
+#if 0
+
+//
+// This function was used to zero out memory in the jnfs.c module.
+// We do not need to do this anymore.
+//
+
+/****
+
+VOID
+WildZeroMemory(
+ IN ULONG StartAddress,
+ IN ULONG Size
+ )
+Routine Description:
+
+ This routine zeroes the specified range of memory.
+
+ At some point this may be changed to a more clever algorithm,
+ For now, it simply does store quads.
+
+Arguments:
+
+ a0 - supplies the base physical address of the range of memory
+ to zero. It must be a multiple of the data cache line
+ size.
+
+ a1 - supplies length of memory to zero, in bytes. This must
+ be a multiple of the data cache line size.
+
+
+Return Value:
+
+ None.
+
+--*/
+
+ LEAF_ENTRY(WildZeroMemory)
+
+ mov a0, t0 # start address
+ mov a1, t1 # number of bytes to move
+
+1:
+ subqv t1, 0x20 # zero a D-cache block = 32 bytes
+ stq zero, (t0)
+ stq zero, 0x8(t0)
+ stq zero, 0x10(t0)
+ stq zero, 0x18(t0)
+ addqv t0, 0x20 # move to next cache block
+ bgt t1, 1b # t1 = 0 when done.
+
+ ret zero, (ra)
+
+ .end WildZeroMemory
+
+#endif
+
+
+/************************************************************
+
+These are stubs. When the real code appears in the Alpha build
+tree, these should be deleted. Consult the "hacked" file.
+
+*************************************************************/
+
+ LEAF_ENTRY(DebugPrompt)
+
+ callpal halt # surprise!
+ ret zero, (ra) # should never return, but...
+
+ .end DebugPrompt
+
+
+
+
+/* ----
+
+VOID
+FwStallExecution
+(
+ ULONG Microseconds
+);
+
+
+This routine utilizes the Alpha cycle counter to delay a requested number of
+microseconds.
+
+
+---- */
+
+ LEAF_ENTRY( FwStallExecution)
+
+ beq a0, 20f // exit if zero delay requested
+
+// lda t0, 20000(zero) // force small delays to 20 milliseconds
+// subl a0, 5, t1
+// cmoveq t1, t0, a0
+
+10: bsr t3, 100f // call 1 microsecond delay subroutine
+
+ subl a0, 1, a0 // decrement requested microseconds
+ zap a0, 0xf0, a0 // unsigned long a0
+
+ bgt a0, 10b
+
+20: ret zero, (ra)
+
+//
+// 1 microsecond delay subroutine
+//
+
+100: ldl t0, CyclesPerMicrosecond // init 1 microsecond delay
+
+ rpcc t1 // get entry time rpcc value
+ zap t1, 0xf0, t1 // clear <63:32>
+
+200: rpcc t2 // get current rpcc value
+ zap t2, 0xf0, t2 // clear <63:32>
+
+ subl t2, t1, t2 // compute unsigned 32b difference
+ zap t2, 0xf0, t2
+
+ subl t0, t2, t2 // (requested delay - delay so far) > 0?
+
+ bgt t2, 200b
+
+ ret zero, (t3)
+
+ .end FwStallExecution
+
+
+
+#endif // ALPHA
+
diff --git a/private/ntos/fw/alpha/jnsetcom.c b/private/ntos/fw/alpha/jnsetcom.c
new file mode 100644
index 000000000..3eefa31d0
--- /dev/null
+++ b/private/ntos/fw/alpha/jnsetcom.c
@@ -0,0 +1,862 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ jnsetcom.c
+
+Abstract:
+
+ This program contains the common routines for the Jensen setup code,
+ the firmware update program (JNUPDATE.EXE), and the FailSafe Booter.
+
+
+Author:
+
+ John DeRosa 31-July-1992.
+
+ This module, and the entire setup program, was based on the jzsetup
+ program written by David M. Robinson (davidro) of Microsoft, dated
+ 9-Aug-1991.
+
+Revision History:
+
+--*/
+
+
+#include "fwp.h"
+#include "jnsnvdeo.h"
+#include "machdef.h"
+#include "string.h"
+#include "iodevice.h"
+#include "jnvendor.h"
+#include "fwstring.h"
+
+
+
+#ifdef ALPHA_FW_SERDEB
+//
+// Variable that enables printing on the COM1 line.
+//
+extern BOOLEAN SerSnapshot;
+#endif
+
+
+#ifndef FAILSAFE_BOOTER
+
+ULONG
+JzDisplayMenu (
+ IN PCHAR Choices[],
+ IN ULONG NumberOfChoices,
+ IN LONG DefaultChoice,
+ IN ULONG CurrentLine,
+ IN LONG AutobootValue,
+ IN BOOLEAN ShowTheTime
+ )
+
+/*++
+
+Routine Description:
+
+ Displays a menu and gets a selection.
+
+ This routine assumes that the entries in the Choices array
+ do not have two adjacent blank rows, and that the first and last
+ rows are not blank.
+
+Arguments:
+
+ Choices[] The menu choices array
+
+ NumberOfChoices The 1-based number of entries in Choices[]
+
+ DefaultChoice The 0-based entry which should be highlighted
+ as the default choice.
+
+ CurrentLine The current line on the video.
+
+ AutobootValue If zero, do not do an autoboot countdown.
+ If nonzero, do an autoboot countdown with this value.
+
+ ShowTheTime If true, the time is displayed in the upper right
+ hand corner.
+
+Return Value:
+
+ Returns -1 if the escape key is pressed, otherwise returns the menu item
+ selected, where 0 is the first item.
+
+--*/
+
+{
+ ULONG Index;
+ UCHAR Character;
+ ULONG Count;
+ ULONG PreviousTime;
+ ULONG RelativeTime;
+ BOOLEAN Timeout;
+
+#ifndef JNUPDATE
+
+ //
+ // Setup for autoboot
+ //
+
+ if (AutobootValue == 0) {
+ Timeout = FALSE;
+ AutobootValue = 1;
+ } else {
+ Timeout = TRUE;
+ PreviousTime = FwGetRelativeTime();
+ }
+
+#else
+
+ Timeout = FALSE;
+ AutobootValue = 1;
+
+#endif
+
+ //
+ // Display the menu
+ //
+
+ for (Index = 0; Index < NumberOfChoices ; Index++ ) {
+ VenSetPosition( Index + CurrentLine, 5);
+ if (Index == DefaultChoice) {
+ VenSetScreenAttributes( TRUE, FALSE, TRUE);
+ VenPrint(Choices[Index]);
+ VenSetScreenAttributes( TRUE, FALSE, FALSE);
+ } else {
+ VenPrint(Choices[Index]);
+ }
+ }
+
+ Character = 0;
+ do {
+#ifndef JNUPDATE
+ if (ShowTheTime) {
+ JzShowTime(FALSE);
+ }
+#endif
+ if (ArcGetReadStatus(ARC_CONSOLE_INPUT) == ESUCCESS) {
+ ArcRead(ARC_CONSOLE_INPUT, &Character, 1, &Count);
+ switch (Character) {
+
+ case ASCII_ESC:
+
+ VenStallExecution(10000);
+ if (ArcGetReadStatus(ARC_CONSOLE_INPUT) == ESUCCESS) {
+ ArcRead(ARC_CONSOLE_INPUT, &Character, 1, &Count);
+ if (Character != '[') {
+ return(-1);
+ }
+ } else {
+ return(-1);
+ }
+
+ // We purposely fall through to ASCII_CSI.
+
+ case ASCII_CSI:
+
+ ArcRead(ARC_CONSOLE_INPUT, &Character, 1, &Count);
+ VenSetPosition( DefaultChoice + CurrentLine, 5);
+ VenPrint(Choices[DefaultChoice]);
+
+ switch (Character) {
+
+ case 'A':
+ case 'D':
+ DefaultChoice--;
+ if (DefaultChoice < 0) {
+ DefaultChoice = NumberOfChoices - 1;
+ }
+ if (*Choices[DefaultChoice] == 0) {
+ DefaultChoice--;
+ }
+ break;
+
+ case 'B':
+ case 'C':
+ DefaultChoice++;
+ if (DefaultChoice == NumberOfChoices) {
+ DefaultChoice = 0;
+ }
+ if (*Choices[DefaultChoice] == 0) {
+ DefaultChoice++;
+ }
+ break;
+
+ case 'H':
+ DefaultChoice = 0;
+ break;
+
+ default:
+ break;
+ }
+
+ VenSetPosition( DefaultChoice + CurrentLine, 5);
+ VenSetScreenAttributes( TRUE, FALSE, TRUE);
+ VenPrint(Choices[DefaultChoice]);
+ VenSetScreenAttributes( TRUE, FALSE, FALSE);
+ continue;
+
+ default:
+ break;
+ }
+ }
+
+ //
+ // If default choice is nonzero and a timeout is active, remove
+ // the timeout.
+ //
+
+ if ((DefaultChoice != 0) && Timeout) {
+ Timeout = FALSE;
+ VenSetPosition(NumberOfChoices + 9, 0);
+ VenPrint("\x9bK");
+ }
+
+#ifndef JNUPDATE
+
+ //
+ // Update the timeout value if active.
+ //
+
+ if (Timeout) {
+ RelativeTime = FwGetRelativeTime();
+ if (RelativeTime != PreviousTime) {
+ PreviousTime = RelativeTime;
+ VenSetPosition(NumberOfChoices + 9, 62);
+ VenPrint("\x9bK");
+ VenPrint1("%d", AutobootValue--);
+ }
+ }
+#endif
+
+ } while ((Character != '\n') && (Character != ASCII_CR) && (AutobootValue >= 0));
+
+ return DefaultChoice;
+}
+#endif
+
+#ifndef FAILSAFE_BOOTER
+GETSTRING_ACTION
+JzGetString(
+ OUT PCHAR String,
+ IN ULONG StringLength,
+ IN PCHAR InitialString OPTIONAL,
+ IN ULONG CurrentRow,
+ IN ULONG CurrentColumn,
+ IN BOOLEAN ShowTheTime
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads a string from standardin until a carriage return is
+ found, StringLength is reached, or ESC is pushed.
+
+ Semicolons are discarded. Reason: semicolons are key characters in
+ the parsing of multi-segment environment variables. They aren not
+ needed for any valid input to the firmware, so the easiest solution
+ is to filter them here.
+
+Arguments:
+
+ String - Supplies a pointer to a location where the string is to be stored.
+
+ StringLength - Supplies the Max Length to read.
+
+ InitialString - Supplies an optional initial string.
+
+ CurrentRow - Supplies the current screen row.
+
+ CurrentColumn - Supplies the current screen column.
+
+ ShowTheTime If true, the time is displayed in the upper
+ right-hand corner of the screen.
+
+Return Value:
+
+ If the string was successfully obtained GetStringSuccess is return,
+ otherwise one of the following codes is returned.
+
+ GetStringEscape - the escape key was pressed or StringLength was reached.
+ GetStringUpArrow - the up arrow key was pressed.
+ GetStringDownArrow - the down arrow key was pressed.
+
+--*/
+
+{
+ ARC_STATUS Status;
+ UCHAR c;
+ ULONG Count;
+ PCHAR Buffer;
+ PCHAR Cursor;
+ PCHAR CopyPointer;
+ GETSTRING_ACTION Action;
+
+ //
+ // If an initial string was supplied, update the output string.
+ //
+
+ if (ARGUMENT_PRESENT(InitialString)) {
+ strcpy(String, InitialString);
+ Buffer = strchr(String, 0);
+ } else {
+ *String = 0;
+ Buffer = String;
+ }
+
+ Cursor = Buffer;
+
+ while (TRUE) {
+
+ //
+ // Print the string.
+ //
+
+ VenSetPosition(CurrentRow, CurrentColumn);
+ VenPrint(String);
+ VenPrint("\x9bK");
+
+ //
+ // Print the cursor.
+ //
+
+ VenSetScreenAttributes(TRUE,FALSE,TRUE);
+ VenSetPosition(CurrentRow, (Cursor - String) + CurrentColumn);
+
+ if (Cursor >= Buffer) {
+ VenPrint(" ");
+ } else {
+ ArcWrite(ARC_CONSOLE_OUTPUT,Cursor,1,&Count);
+ }
+ VenSetScreenAttributes(TRUE,FALSE,FALSE);
+
+#ifndef JNUPDATE
+ while (ShowTheTime &&
+ ArcGetReadStatus(ARC_CONSOLE_INPUT) != ESUCCESS) {
+ JzShowTime(FALSE);
+ }
+#endif
+ Status = ArcRead(ARC_CONSOLE_INPUT,&c,1,&Count);
+
+ if (Status != ESUCCESS) {
+ Action = GetStringEscape;
+ goto EndGetString;
+ }
+
+ if (Buffer-String == StringLength) {
+ Action = GetStringEscape;
+ goto EndGetString;
+ }
+
+ switch (c) {
+
+ case ASCII_ESC:
+
+ //
+ // If there is another character available, look to see if
+ // this a control sequence, and fall through to ASCII_CSI.
+ // This is an attempt to make escape sequences from a terminal work.
+ //
+
+ VenStallExecution(10000);
+
+ if (ArcGetReadStatus(ARC_CONSOLE_INPUT) == ESUCCESS) {
+ ArcRead(ARC_CONSOLE_INPUT, &c, 1, &Count);
+ if (c != '[') {
+ Action = GetStringEscape;
+ goto EndGetString;
+ }
+ } else {
+ Action = GetStringEscape;
+ goto EndGetString;
+ }
+
+ case ASCII_CSI:
+
+ ArcRead(ARC_CONSOLE_INPUT, &c, 1, &Count);
+ switch (c) {
+
+ case 'A':
+ Action = GetStringUpArrow;
+ goto EndGetString;
+
+ case 'D':
+ if (Cursor != String) {
+ Cursor--;
+ }
+ continue;
+
+ case 'B':
+ Action = GetStringDownArrow;
+ goto EndGetString;
+
+ case 'C':
+ if (Cursor != Buffer) {
+ Cursor++;
+ }
+ continue;
+
+ case 'H':
+ Cursor = String;
+ continue;
+
+ case 'K':
+ Cursor = Buffer;
+ continue;
+
+ case 'P':
+ CopyPointer = Cursor;
+ while (*CopyPointer) {
+ *CopyPointer = *(CopyPointer + 1);
+ CopyPointer++;
+ }
+ if (Buffer != String) {
+ Buffer--;
+ }
+ continue;
+
+ default:
+ break;
+ }
+ break;
+
+ case '\r':
+ case '\n':
+
+ Action = GetStringSuccess;
+ goto EndGetString;
+
+ //
+ // Do not bother handling the tab character properly.
+ //
+
+ case '\t' :
+
+ Action = GetStringEscape;
+ goto EndGetString;
+
+ case '\b':
+
+ if (Cursor != String) {
+ Cursor--;
+ }
+ CopyPointer = Cursor;
+ while (*CopyPointer) {
+ *CopyPointer = *(CopyPointer + 1);
+ CopyPointer++;
+ }
+ if (Buffer != String) {
+ Buffer--;
+ }
+ break;
+
+ //
+ // Discard any semicolons because they will corrupt multi-
+ // segment environment variables.
+ //
+
+ case ';':
+
+ break;
+
+ default:
+
+ //
+ // Store the character.
+ //
+
+ CopyPointer = ++Buffer;
+ if (CopyPointer > Cursor) {
+ while (CopyPointer != Cursor) {
+ *CopyPointer = *(CopyPointer - 1);
+ CopyPointer--;
+ }
+ }
+ *Cursor++ = c;
+ break;
+ }
+ }
+
+ Action = GetStringEscape;
+
+EndGetString:
+
+ VenSetPosition(CurrentRow, (Cursor - String) + CurrentColumn);
+
+ if (Cursor >= Buffer) {
+ VenPrint(" ");
+ } else {
+ ArcWrite(ARC_CONSOLE_OUTPUT,Cursor,1,&Count);
+ }
+
+ //
+ // Make sure we return a null string if not successful.
+ //
+
+ if (Action != GetStringSuccess) {
+ *String = 0;
+ }
+
+ return(Action);
+}
+
+#endif
+
+#if !defined(JNUPDATE) && !defined(FAILSAFE_BOOTER)
+ARC_STATUS
+JzEnvironmentCheckChecksum (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine checks the environment area checksum.
+
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the checksum is good, ESUCCESS is returned, otherwise EIO is returned.
+
+--*/
+
+{
+ PUCHAR NvChars;
+ PNV_CONFIGURATION NvConfiguration;
+ ULONG Index;
+ ULONG Checksum1, Checksum2;
+
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
+
+ //
+ // Form checksum from NVRAM data.
+ //
+
+ Checksum1 = 0;
+ NvChars = (PUCHAR)&NvConfiguration->Environment[0];
+
+ for ( Index = 0 ;
+ Index < LENGTH_OF_ENVIRONMENT;
+ Index++ ) {
+ Checksum1 += HalpReadNVByte( NvChars++ );
+ }
+
+ //
+ // Reconstitute checksum and return error if no compare.
+ //
+
+ Checksum2 = (ULONG)HalpReadNVByte( &NvConfiguration->Checksum2[0] ) |
+ (ULONG)HalpReadNVByte( &NvConfiguration->Checksum2[1] ) << 8 |
+ (ULONG)HalpReadNVByte( &NvConfiguration->Checksum2[2] ) << 16 |
+ (ULONG)HalpReadNVByte( &NvConfiguration->Checksum2[3] ) << 24 ;
+
+ if (Checksum1 != Checksum2) {
+ return EIO;
+ } else {
+ return ESUCCESS;
+ }
+}
+#endif
+
+#ifndef JNUPDATE
+BOOLEAN
+JzGetPathMnemonicKey(
+ IN PCHAR OpenPath,
+ IN PCHAR Mnemonic,
+ IN PULONG Key
+ )
+
+/*++
+
+Routine Description:
+
+ This routine looks for the given Mnemonic in OpenPath.
+ If Mnemonic is a component of the path, then it converts the key
+ value to an integer wich is returned in Key.
+
+Arguments:
+
+ OpenPath - Pointer to a string that contains an ARC pathname.
+
+ Mnemonic - Pointer to a string that contains a ARC Mnemonic
+
+ Key - Pointer to a ULONG where the Key value is stored.
+
+
+Return Value:
+
+ FALSE if mnemonic is found in path and a valid key is converted.
+ TRUE otherwise.
+
+--*/
+
+{
+
+ PCHAR Tmp;
+ CHAR Digits[4];
+ ULONG i;
+ CHAR String[16];
+
+ //
+ // Construct a string of the form ")mnemonic("
+ //
+ String[0]=')';
+ for(i=1;*Mnemonic;i++) {
+ String[i] = * Mnemonic++;
+ }
+ String[i++]='(';
+ String[i]='\0';
+
+ if ((Tmp=strstr(OpenPath,&String[1])) == NULL) {
+ return TRUE;
+ }
+
+ if (Tmp != OpenPath) {
+ if ((Tmp=strstr(OpenPath,String)) == NULL) {
+ return TRUE;
+ }
+ } else {
+ i--;
+ }
+ //
+ // skip the mnemonic and convert the value in between parentesis to integer
+ //
+ Tmp+=i;
+ for (i=0;i<3;i++) {
+ if (*Tmp == ')') {
+ Digits[i] = '\0';
+ break;
+ }
+ Digits[i] = *Tmp++;
+ }
+ Digits[i]='\0';
+ *Key = atoi(Digits);
+ return FALSE;
+}
+
+#endif // ndef JNUPDATE
+
+VOID
+FwWaitForKeypress(
+ IN BOOLEAN ShowTheTime
+ )
+
+/*++
+
+Routine Description:
+
+ This routine waits for a keypress, then returns.
+
+Arguments:
+
+ ShowTheTime TRUE = display the time.
+ FALSE = do not display the time.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR Character;
+ ULONG Count;
+
+ VenPrint(SS_PRESS_KEY_MSG);
+ while (ArcGetReadStatus(ARC_CONSOLE_INPUT) != ESUCCESS) {
+#if !defined(JNUPDATE) && !defined(FAILSAFE_BOOTER)
+ if (ShowTheTime) {
+ JzShowTime(FALSE);
+ }
+#endif
+ }
+ ArcRead(ARC_CONSOLE_INPUT, &Character, 1, &Count);
+ VenPrint1("%c2J", ASCII_CSI);
+}
+
+#if !defined(JNUPDATE) && !defined(FAILSAFE_BOOTER)
+
+BOOLEAN
+FwGetVariableSegment (
+ IN ULONG SegmentNumber,
+ IN OUT PCHAR Segment
+ )
+
+/*++
+
+Routine Description:
+
+ This routine returns the specified segment of a volatile environment
+ variable. Segments are separated by semicolons.
+
+Arguments:
+
+ SegmentNumber - Supplies the number of the segment to return.
+
+ Segment - Supplies a pointer to the name of the environment variable.
+ The variable may be followed by an equal sign.
+ An '=' and the segment value are appended to this name and
+ returned.
+
+
+Return Value:
+
+ If one or more segments exist after the specified segment, TRUE is returned,
+ otherwise FALSE is returned.
+
+--*/
+
+{
+ ULONG Index;
+ ULONG Count;
+ PCHAR VariableValue;
+ PCHAR TempPointer;
+
+ //
+ // Remove an equal sign if present.
+ //
+
+ if ((TempPointer = strchr(Segment, '=')) != NULL) {
+ *TempPointer = 0;
+ }
+
+ //
+ // Get variable, add equal sign, and advance Segment to where the value
+ // is to be added.
+ //
+
+ VariableValue = FwGetVolatileEnvironmentVariable(Segment);
+ strcat(Segment, "=");
+ Segment = strchr(Segment, '=') + 1;
+
+ //
+ // If there was no variable, return.
+ //
+
+ if (VariableValue == NULL) {
+ return(FALSE);
+ }
+
+ Index = 0;
+ Count = 0;
+
+ //
+ // Search for the requested segment and copy it to the return value.
+ //
+
+ while ((TempPointer = strchr(VariableValue,';')) != NULL) {
+ Count = TempPointer - VariableValue;
+
+ if (Index == SegmentNumber) {
+ strncpy(Segment, VariableValue, Count);
+ Segment[Count] = 0;
+ return TRUE;
+ }
+
+ VariableValue += Count + 1;
+ Index++;
+ }
+
+ //
+ // If there is data left, copy it to the return value.
+ //
+
+ strcpy(Segment,VariableValue);
+
+ return(FALSE);
+}
+
+#endif
+
+#if !defined(JNUPDATE) && !defined(FAILSAFE_BOOTER)
+
+ARC_STATUS
+FwSetVariableSegment (
+ IN ULONG SegmentNumber,
+ IN PCHAR VariableName,
+ IN PCHAR NewSegment
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the specified segment of an environment variable
+ IN THE VOLATILE AREA ONLY. Segments are separated by semicolons.
+
+Arguments:
+
+ SegmentNumber - Supplies the number of the segment to add.
+
+ VariableName - Supplies a pointer to the name of the environment variable.
+ The variable may be followed by an equal sign.
+
+ NewSegment - Supplies a pointer to the new segment.
+
+Return Value:
+
+ Returns ESUCCESS if the segment is set, otherwise an error code is
+ returned.
+
+--*/
+
+{
+ ARC_STATUS Status;
+ PCHAR Variable;
+ PCHAR NextVariable;
+ PCHAR EndOfVariable;
+ CHAR VariableValue[256];
+ ULONG Index;
+ ULONG Count;
+
+ SetupROMPendingModified = TRUE;
+
+ Variable = FwGetVolatileEnvironmentVariable(VariableName);
+ VariableValue[0] = 0;
+
+ if (Variable != NULL) {
+ EndOfVariable = strchr(Variable, 0);
+ for (Index = 0; Index < SegmentNumber ; Index++ ) {
+ NextVariable = strchr(Variable, ';');
+ if (NextVariable != NULL) {
+ Count = NextVariable - Variable + 1;
+ strncat(VariableValue, Variable, Count);
+ Variable = NextVariable + 1;
+ } else {
+ strcat(VariableValue, Variable);
+ Variable = EndOfVariable;
+ strcat(VariableValue, ";");
+ }
+ }
+ } else {
+ for (Index = 0; Index < SegmentNumber ; Index++ ) {
+ strcat(VariableValue, ";");
+ }
+ }
+
+ strcat(VariableValue, NewSegment);
+
+ if ((Variable != NULL) && (Variable != EndOfVariable)) {
+ strcat(VariableValue, ";");
+ strcat(VariableValue, Variable);
+ }
+
+ Status = FwCoreSetEnvironmentVariable(VariableName, VariableValue, FALSE);
+ SetupROMPendingModified = TRUE;
+ return(Status);
+}
+
+#endif
diff --git a/private/ntos/fw/alpha/jnsetenv.c b/private/ntos/fw/alpha/jnsetenv.c
new file mode 100644
index 000000000..a091f7793
--- /dev/null
+++ b/private/ntos/fw/alpha/jnsetenv.c
@@ -0,0 +1,408 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ jnsetenv.c
+
+Abstract:
+
+ This module contains the code to change an environment variable.
+
+ This module is Jensen-specific.
+
+
+Author:
+
+ John DeRosa 31-July-1992.
+
+ This module, and the entire setup program, was based on the jzsetup
+ program written by David M. Robinson (davidro) of Microsoft, dated
+ 9-Aug-1991.
+
+
+Revision History:
+
+--*/
+
+
+#include "fwp.h"
+#include "jnsnvdeo.h"
+#include "machdef.h"
+#include "string.h"
+#include "iodevice.h"
+#include "jnvendor.h"
+#include "fwstring.h"
+
+//
+// Environment variables.
+//
+
+PCHAR BootString[] = { "LOADIDENTIFIER",
+ "SYSTEMPARTITION",
+ "OSLOADER",
+ "OSLOADPARTITION",
+ "OSLOADFILENAME",
+ "OSLOADOPTIONS" };
+
+BOOLEAN
+JzSetBootEnvironmentVariable (
+ IN ULONG CurrentBootSelection
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allows the user to edit boot environment variables.
+
+Arguments:
+
+ CurrentBootSelection - Supplies the current segment number to edit.
+
+Return Value:
+
+ Returns true if a variable was set, FALSE if ESC was pressed.
+
+--*/
+
+{
+ ARC_STATUS Status;
+ LONG Index;
+ PCHAR Variable;
+ PCHAR LastVariable;
+ CHAR VariableName[32];
+ CHAR VariableValue[128];
+ CHAR Segment[128];
+ GETSTRING_ACTION Action;
+ PCHAR NextVariable;
+
+ Index = 0;
+ do {
+
+ VenSetPosition( 4, 5);
+ VenPrint("\x9bK");
+ VenPrint(SS_NAME_MSG);
+ Action = JzGetString( VariableName,
+ sizeof(VariableName),
+ BootString[Index],
+ 4,
+ 5 + strlen(SS_NAME_MSG),
+ TRUE
+ );
+ switch (Action) {
+
+ case GetStringEscape:
+ return(FALSE);
+
+ case GetStringUpArrow:
+ if (Index == 0) {
+ Index = 5;
+ } else {
+ Index--;
+ }
+ break;
+
+ case GetStringDownArrow:
+ if (Index == 5) {
+ Index = 0;
+ } else {
+ Index++;
+ }
+ break;
+
+ default:
+ continue;
+
+ }
+
+ } while (Action != GetStringSuccess);
+
+ if (VariableName[0] == 0) {
+ return(FALSE);
+ }
+
+ Variable = NULL;
+
+ SetupROMPendingModified = TRUE;
+
+ Action = GetStringUpArrow;
+ do {
+
+ switch (Action) {
+
+ case GetStringEscape:
+ return(FALSE);
+
+ case GetStringUpArrow:
+ case GetStringDownArrow:
+ if (Variable == NULL) {
+ strcpy(Segment, VariableName);
+ FwGetVariableSegment( CurrentBootSelection, Segment );
+ strcpy(VariableValue, strchr(Segment, '=') + 1);
+ Variable = VariableValue;
+ } else {
+ Variable = NULL;
+ }
+ break;
+
+ default:
+ continue;
+ }
+
+ VenSetPosition( 5, 5);
+ VenPrint("\x9bK");
+ VenPrint(SS_VALUE_MSG);
+
+ Action = JzGetString( VariableValue,
+ sizeof(VariableValue),
+ Variable,
+ 5,
+ 5 + strlen(SS_VALUE_MSG),
+ TRUE
+ );
+
+ } while (Action != GetStringSuccess );
+
+
+ //
+ // Save the old value.
+ //
+
+ strcpy(Segment, VariableName);
+ FwGetVariableSegment( CurrentBootSelection, Segment );
+
+ //
+ // Delete the old value.
+ //
+
+ JzDeleteVariableSegment( VariableName, CurrentBootSelection );
+
+ //
+ // Add in the new value.
+ //
+
+ Status = FwSetVariableSegment( CurrentBootSelection,
+ VariableName,
+ VariableValue );
+
+ if (Status != ESUCCESS) {
+
+ //
+ // Try to add back in the old value.
+ //
+
+ FwSetVariableSegment( CurrentBootSelection,
+ VariableName,
+ strchr(Segment, '=') + 1);
+
+ VenSetPosition(7, 5);
+ if (Status == ENOSPC) {
+ VenPrint(SS_NO_NVRAM_SPACE_MSG);
+ } else {
+ VenPrint(SS_NVRAM_CHKSUM_MSG);
+ }
+ VenPrint(SS_PRESS_KEY2_MSG);
+ FwWaitForKeypress(TRUE);
+ return(FALSE);
+ }
+
+ return(TRUE);
+}
+
+BOOLEAN
+JzSetEnvironmentVariable (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allow the user to edit environment variables other than
+ the ones for boot.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns true if a variable was set, FALSE if ESC was pressed.
+
+--*/
+
+{
+ ARC_STATUS Status;
+ LONG Index;
+ ULONG Position;
+ PCHAR EqualSign;
+ ULONG EnvironmentIndex;
+ PCHAR Variable;
+ PCHAR LastVariable;
+ CHAR VariableName[32];
+ CHAR InitialVariableName[32];
+ CHAR VariableValue[256];
+ CHAR Segment[256];
+ GETSTRING_ACTION Action;
+ PCHAR Environment;
+
+ SetupROMPendingModified = TRUE;
+
+ //
+ // Index of '0' is a blank entry, so the user can fill out a new environment
+ // variable if required.
+ //
+
+ Variable = NULL;
+ Index = 0;
+ do {
+
+ VenSetPosition( 5, 5);
+ VenPrint("\x9bK");
+ VenPrint(SS_NAME_MSG);
+ Action = JzGetString( VariableName,
+ sizeof(VariableName),
+ Variable,
+ 5,
+ 5 + strlen(SS_NAME_MSG),
+ TRUE
+ );
+ switch (Action) {
+
+ case GetStringEscape:
+ return(FALSE);
+
+ case GetStringUpArrow:
+ Index--;
+ break;
+
+ case GetStringDownArrow:
+ Index++;
+ break;
+
+ default:
+ continue;
+
+ }
+
+ Environment = VolatileEnvironment;
+ LastVariable = Environment;
+ EnvironmentIndex = 1;
+ while (TRUE) {
+
+ //
+ // Jump over any boot variables.
+ //
+
+ while((strstr(Environment, "SYSTEMPARTITION=") != NULL) ||
+ (strstr(Environment, "OSLOADER=") != NULL) ||
+ (strstr(Environment, "OSLOADPARTITION=") != NULL) ||
+ (strstr(Environment, "OSLOADFILENAME=") != NULL) ||
+ (strstr(Environment, "OSLOADOPTIONS=") != NULL) ||
+ (strstr(Environment, "LOADIDENTIFIER=") != NULL)) {
+ Environment = strchr(Environment, '\0') + 1;
+ if (*Environment == 0) {
+ break;
+ }
+ }
+
+ //
+ // The end of the environment was reached without matching
+ // the index. If the index is less than zero, set it to
+ // the last variable found, otherwise set it to 0.
+ //
+
+ if (*Environment == 0) {
+ EnvironmentIndex--;
+ if (Index < 0) {
+ Environment = LastVariable;
+ Index = EnvironmentIndex;
+ } else {
+ Index = 0;
+ Variable = NULL;
+ break;
+ }
+ }
+
+ //
+ // We're on the right variable.
+ //
+
+ if (Index == EnvironmentIndex) {
+
+ InitialVariableName[0] = 0;
+ EqualSign = strchr(Environment, '=');
+ if (EqualSign != NULL) {
+ Position = EqualSign - Environment;
+ strncpy(InitialVariableName, Environment, Position);
+ InitialVariableName[Position] = 0;
+ }
+ Variable = InitialVariableName;
+ break;
+ }
+
+ LastVariable = Environment;
+ Environment = strchr(Environment, '\0') + 1;
+ EnvironmentIndex++;
+ }
+
+ } while (Action != GetStringSuccess);
+
+ if (VariableName[0] == 0) {
+ return(FALSE);
+ }
+
+ Variable = NULL;
+ Action = GetStringUpArrow;
+ do {
+ switch (Action) {
+
+ case GetStringEscape:
+ return(FALSE);
+
+ case GetStringUpArrow:
+ case GetStringDownArrow:
+ if (Variable == NULL) {
+ Variable = ArcGetEnvironmentVariable(VariableName);
+ } else {
+ Variable = NULL;
+ }
+ break;
+
+ default:
+ continue;
+ }
+
+ VenSetPosition( 6, 5);
+ VenPrint("\x9bK");
+ VenPrint(SS_VALUE_MSG);
+
+ Action = JzGetString( VariableValue,
+ sizeof(VariableValue),
+ Variable,
+ 6,
+ 5 + strlen(SS_VALUE_MSG),
+ TRUE
+ );
+ } while (Action != GetStringSuccess );
+
+ if ((Status = FwCoreSetEnvironmentVariable(VariableName,
+ VariableValue,
+ FALSE)) != ESUCCESS) {
+ VenSetPosition(7, 5);
+ if (Status == ENOSPC) {
+ VenPrint(SS_NO_NVRAM_SPACE_MSG);
+ } else {
+ VenPrint(SS_NVRAM_CHKSUM_MSG);
+ }
+ VenPrint(SS_PRESS_KEY2_MSG);
+ FwWaitForKeypress(TRUE);
+ return(FALSE);
+ }
+
+ return(TRUE);
+}
+
diff --git a/private/ntos/fw/alpha/jnsetmak.c b/private/ntos/fw/alpha/jnsetmak.c
new file mode 100644
index 000000000..6edc1283f
--- /dev/null
+++ b/private/ntos/fw/alpha/jnsetmak.c
@@ -0,0 +1,2442 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ jnsetmak.c
+
+Abstract:
+
+ This module contains the code to make the configuration and environment
+ variable data structures in the Jensen PROM, and the firmware diagnostic
+ flags in the Jensen NVRAM.
+
+ This module is Jensen-specific.
+
+
+Author:
+
+ John DeRosa 31-July-1992
+
+ This module, and the entire setup program, was based on the jzsetup
+ program written by David M. Robinson (davidro) of Microsoft, dated
+ 9-Aug-1991.
+
+
+Revision History:
+
+--*/
+
+
+#include "fwp.h"
+#include "jnsnvdeo.h"
+#include "machdef.h"
+#include "string.h"
+#include "iodevice.h"
+#include "jnvendor.h"
+#include "fwstring.h"
+#include "xxstring.h"
+
+
+//
+// 1-based number of video screen rows, from jxdisp.c module.
+//
+extern ULONG DisplayHeight;
+
+
+//
+// Routine prototypes.
+//
+
+VOID
+JzMakeConfiguration (
+ ULONG Monitor,
+ ULONG Floppy,
+ ULONG Floppy2
+ );
+
+VOID
+JzAddBootSelection (
+ IN BOOLEAN DoFactoryDefaults
+ );
+
+VOID
+JzGoToCurrentLinePosition (
+ IN ULONG SizeOfMenuArea,
+ IN OUT PULONG CurrentLine,
+ OUT PULONG MenuLine
+ )
+
+/*++
+
+Routine Description:
+
+ This function handles the setting of the current screen line
+ for the JzGetxxxxx functions that require it.
+
+Arguments:
+
+ SizeOfMenuArea The number of menu choices for the call to
+ JzDisplayMenu.
+
+ CurrentLine (In) A pointer to the value of the current screen line.
+ (Out) This is updated to where the caller should
+ do a VenSetPosition to after displaying the menu.
+
+ MenuLine A pointer to the screen line where the menu
+ area starts.
+
+Return Value:
+
+ None. The video cursor position is left at the line where the menu
+ should be displayed.
+
+--*/
+
+{
+ //
+ // If we are past the bottom of the video screen, set the current
+ // position at the bottom.
+ //
+
+ if (*CurrentLine > DisplayHeight) {
+ *CurrentLine = DisplayHeight;
+ }
+
+ //
+ // Set the callers menu area to the current line and point the current
+ // line past the menu area.
+ //
+
+ *MenuLine = *CurrentLine;
+ *CurrentLine += SizeOfMenuArea;
+
+ //
+ // If the new current line is past the bottom of the screen, scroll the
+ // screen accordingly and adjust the menu line.
+ //
+
+ while (*CurrentLine > DisplayHeight) {
+ VenSetPosition(DisplayHeight, 0);
+ VenPrint("\n");
+ (*CurrentLine)--;
+ (*MenuLine)--;
+ }
+
+
+ //
+ // Now set the current screen cursor to where the menu should begin
+ // and return.
+ //
+
+ VenSetPosition(*MenuLine, 0);
+
+ return;
+}
+
+VOID
+JzMakeEnvironment (
+ ULONG Device,
+ ULONG DeviceId,
+ ULONG DevicePartition
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the environment variables.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ CHAR TempString[80];
+
+ SetupROMPendingModified = TRUE;
+
+ //
+ // Create the SYSTEMPARTITION environment variable value string.
+ //
+
+ switch (Device) {
+ case 0:
+ sprintf(TempString,
+ "scsi()disk(%1d)rdisk()partition(%1d)",
+ DeviceId,
+ DevicePartition);
+ break;
+ default:
+ sprintf(TempString,
+ "scsi()cdrom(%1d)fdisk()",
+ DeviceId);
+ break;
+ }
+
+
+ if (FwCoreSetEnvironmentVariable("CONSOLEIN",
+ FW_KEYBOARD_IN_DEVICE,
+ FALSE) != ESUCCESS) {
+ goto TestError;
+ }
+
+ if (FwCoreSetEnvironmentVariable("CONSOLEOUT",
+ FW_CONSOLE_OUT_DEVICE,
+ FALSE) != ESUCCESS) {
+ goto TestError;
+ }
+
+ if (FwCoreSetEnvironmentVariable("FWSEARCHPATH",
+ TempString,
+ FALSE) != ESUCCESS) {
+ goto TestError;
+ }
+
+ if (FwCoreSetEnvironmentVariable("SYSTEMPARTITION",
+ TempString,
+ FALSE) != ESUCCESS) {
+ goto TestError;
+ }
+
+ if (FwCoreSetEnvironmentVariable("TIMEZONE",
+ "PST8PDT",
+ FALSE) != ESUCCESS) {
+ goto TestError;
+ }
+
+ if (FwCoreSetEnvironmentVariable("A:",
+ FW_FLOPPY_0_DEVICE,
+ FALSE) != ESUCCESS) {
+ goto TestError;
+ }
+
+ return;
+
+
+TestError:
+
+ VenPrint(SS_CANT_SET_VARIABLE_MSG);
+ return;
+}
+
+
+
+//
+// Currently, Alpha machines with EISA busses have the console video
+// hanging off the EISA bus. And therefore, setting up the video type
+// is the responsibility of the ECU.
+//
+// So the correct ifdef for this function is ifdef ISA_PLATFORM.
+//
+// A machine with a video hanging off a local bus that is *not* configured
+// by a configuration utility may need to change this compilation test.
+//
+
+#ifdef ISA_PLATFORM
+
+ULONG
+JzGetMonitor (
+ IN PULONG CurrentLine
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG Line;
+ ULONG ReturnValue;
+
+ //
+ // Make space for the menu on the screen.
+ //
+
+ JzGoToCurrentLinePosition(NUMBER_OF_RESOLUTIONS + 2,
+ CurrentLine,
+ &Line);
+
+ VenPrint(SS_SELECT_MONITOR_RESOLUTION_MSG);
+
+ ReturnValue = JzDisplayMenu( ResolutionChoices,
+ NUMBER_OF_RESOLUTIONS,
+ 0,
+ Line + 1,
+ 0,
+ TRUE);
+
+ VenSetPosition( *CurrentLine, 0);
+ return ReturnValue;
+}
+
+#endif
+
+
+
+ULONG
+JzGetFloppy (
+ IN PULONG CurrentLine
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG Line;
+ ULONG ReturnValue;
+
+ //
+ // Make space for the menu on the screen.
+ //
+
+ JzGoToCurrentLinePosition(NUMBER_OF_FLOPPIES + 2,
+ CurrentLine,
+ &Line);
+
+ VenPrint(SS_FLOPPY_SIZE_MSG);
+
+ ReturnValue = JzDisplayMenu( FloppyChoices,
+ NUMBER_OF_FLOPPIES,
+ 2,
+ Line + 1,
+ 0,
+ TRUE);
+
+ VenSetPosition( *CurrentLine, 0);
+ return ReturnValue;
+}
+
+
+ULONG
+JzGetYesNo (
+ IN PULONG CurrentLine,
+ IN PCHAR PromptString,
+ IN BOOLEAN YesIsDefault
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG Line;
+ ULONG ReturnValue;
+
+ //
+ // Make space for the menu on the screen.
+ //
+
+ JzGoToCurrentLinePosition(NUMBER_OF_YES_NO + 2,
+ CurrentLine,
+ &Line);
+
+ VenPrint(PromptString);
+
+ ReturnValue = JzDisplayMenu( YesNoChoices,
+ NUMBER_OF_YES_NO,
+ YesIsDefault ? 0 : 1,
+ Line + 1,
+ 0,
+ TRUE);
+
+ VenSetPosition( *CurrentLine, 0);
+ return ReturnValue;
+}
+
+
+ULONG
+JzGetDevice (
+ IN PULONG CurrentLine
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG Line;
+ ULONG ReturnValue;
+
+ //
+ // Make space for the menu on the screen.
+ //
+
+ JzGoToCurrentLinePosition(NUMBER_OF_MEDIA + 2,
+ CurrentLine,
+ &Line);
+
+ VenPrint(SS_SELECT_MEDIA_MSG);
+
+ ReturnValue = JzDisplayMenu( MediaChoices,
+ NUMBER_OF_MEDIA,
+ 0,
+ Line + 1,
+ 0,
+ TRUE);
+
+ VenSetPosition( *CurrentLine, 0);
+ return ReturnValue;
+}
+
+
+ULONG
+JzGetDeviceId (
+ IN PULONG CurrentLine,
+ IN ULONG DeviceMediaType
+ )
+
+/*++
+
+Routine Description:
+
+ This is used to prompt for SCSI IDs and floppy drive numbers.
+
+Arguments:
+
+ CurrentLine The current line on the screen.
+
+ DeviceMediaType The index of MediaChoices[] for the device type
+ that we are getting an ID for. This dictates the
+ initial and maximum allowed device IDs, and the
+ prompt to the user, as follows:
+
+ DeviceMediaType Device Initial Maximum
+ 0 SCSI disk 0 7
+ 1 floppy 0 1
+ 2 SCSI CDROM 4 7
+
+
+ DeviceMediaType = 0 or 2: ask for SCSI ID.
+ DeviceMediaType = 1: ask for floppy number.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PUCHAR Prompt;
+ ULONG Line;
+ ULONG ReturnValue;
+ CHAR TempString[5];
+ GETSTRING_ACTION Action;
+ ULONG InitialValue;
+ ULONG MaximumValue;
+
+ switch (DeviceMediaType) {
+
+ case 0:
+
+ InitialValue = 0;
+ MaximumValue = 7;
+ Prompt = SS_ENTER_SCSI_ID_MSG;
+ break;
+
+ case 1:
+
+ InitialValue = 0;
+ MaximumValue = 1;
+ Prompt = SS_ENTER_FLOPPY_DRIVE_NUMBER_MSG;
+ break;
+
+ case 2:
+
+ InitialValue = 4;
+ MaximumValue = 7;
+ Prompt = SS_ENTER_SCSI_ID_MSG;
+ break;
+
+ default:
+
+ // Something is wrong. Do an error return.
+ return (0);
+
+ }
+
+ //
+ // Make space for the prompt on the screen.
+ //
+
+ JzGoToCurrentLinePosition(1,
+ CurrentLine,
+ &Line);
+
+ while (TRUE) {
+ VenSetPosition( Line, 0);
+
+ VenPrint(Prompt);
+ VenPrint("\x9bK");
+
+ sprintf(TempString, "%1d", InitialValue);
+
+ do {
+ Action = JzGetString( TempString,
+ sizeof(TempString),
+ TempString,
+ Line,
+ strlen(Prompt) + 1,
+ TRUE);
+
+ if (Action == GetStringEscape) {
+ return(-1);
+ }
+
+ } while ( Action != GetStringSuccess );
+
+ ReturnValue = atoi(TempString);
+
+ if ((ReturnValue >= 0) && (ReturnValue <= MaximumValue)) {
+ break;
+ }
+ }
+
+ VenSetPosition( *CurrentLine, 0);
+ return ReturnValue;
+}
+
+ULONG
+JzGetCountdownValue (
+ IN PULONG CurrentLine
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG Line;
+ ULONG ReturnValue;
+ CHAR TempString[5];
+ GETSTRING_ACTION Action;
+
+ //
+ // Make space for the prompt on the screen.
+ //
+
+ JzGoToCurrentLinePosition(1,
+ CurrentLine,
+ &Line);
+
+ VenPrint(SS_COUNTDOWN_MSG);
+ VenPrint("\x9bK");
+
+ do {
+ Action = JzGetString( TempString,
+ sizeof(TempString),
+ "10",
+ Line,
+ strlen(SS_COUNTDOWN_MSG),
+ TRUE);
+
+ if (Action == GetStringEscape) {
+ return(-1);
+ }
+
+ } while ( Action != GetStringSuccess );
+
+ ReturnValue = atoi(TempString);
+ VenSetPosition( *CurrentLine, 0);
+
+ return ReturnValue;
+}
+
+ULONG
+JzGetPartition (
+ IN PULONG CurrentLine,
+ IN BOOLEAN MustBeFatOrNtfs
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG Line;
+ ULONG ReturnValue;
+ CHAR TempString[5];
+ GETSTRING_ACTION Action;
+
+ //
+ // Make space for the prompt on the screen.
+ //
+
+ JzGoToCurrentLinePosition(1,
+ CurrentLine,
+ &Line);
+
+ while (TRUE) {
+ VenSetPosition( Line, 0);
+
+ if (MustBeFatOrNtfs) {
+ VenPrint(SS_ENTER_FAT_OR_NTFS_PART_MSG);
+ VenPrint("\x9bK");
+
+ do {
+ Action = JzGetString( TempString,
+ sizeof(TempString),
+ "1",
+ Line,
+ strlen(SS_ENTER_FAT_OR_NTFS_PART_MSG),
+ TRUE);
+
+ if (Action == GetStringEscape) {
+ return(-1);
+ }
+
+ } while ( Action != GetStringSuccess );
+
+ } else {
+ VenPrint(SS_ENTER_PART_MSG);
+ VenPrint("\x9bK");
+
+ do {
+ Action = JzGetString( TempString,
+ sizeof(TempString),
+ "1",
+ Line,
+ strlen(SS_ENTER_PART_MSG),
+ TRUE);
+
+ if (Action == GetStringEscape) {
+ return(-1);
+ }
+
+ } while ( Action != GetStringSuccess );
+
+ }
+
+ ReturnValue = atoi(TempString);
+
+ if ((ReturnValue >= 0) && (ReturnValue <= 9)) {
+ break;
+ }
+ }
+
+ VenSetPosition( *CurrentLine, 0);
+ return ReturnValue;
+}
+
+ARC_STATUS
+JzPickSystemPartition (
+ OUT PCHAR SystemPartition,
+ IN OUT PULONG CurrentLine
+ )
+
+/*++
+
+Routine Description:
+
+ This routine picks a system partition from the FWSEARCHPATH or
+ SYSTEMPARTITION environment variables, or builds a new one.
+
+Arguments:
+
+ SystemPartition - Supplies a pointer to a character array to receive the
+ system partition.
+
+ CurrentLine - The current display line.
+
+Return Value:
+
+ If a system partition is picked, ESUCCESS is returned, otherwise an error
+ code is returned.
+
+--*/
+{
+ CHAR Variable[128];
+ PCHAR Segment;
+ ULONG NumberOfChoices;
+ ULONG Index, i;
+ BOOLEAN More;
+ BOOLEAN FoundOne;
+ ULONG Line;
+ ULONG SecondPass;
+ ULONG Device[10]; // 0 = scsi disk, 1 = floppy, 2 = cdrom
+ ULONG DeviceId[10];
+ ULONG DevicePartition[10];
+ ULONG Key;
+ CHAR MenuItem[11][40];
+ PCHAR Menu[10];
+
+ //
+ // Loop through the FWSEARCHPATH and SYSTEMPARTITION variables
+ // for potential system partitions.
+ //
+
+ NumberOfChoices = 0;
+ SecondPass = 0;
+
+ do {
+
+ Index = 0;
+ if (!SecondPass) {
+ strcpy(Variable, "FWSEARCHPATH");
+ } else {
+ strcpy(Variable, BootString[SystemPartitionVariable]);
+ }
+
+ do {
+ FoundOne = FALSE;
+ More = FwGetVariableSegment(Index++, Variable);
+
+ //
+ // Advance to the segment.
+ //
+ Segment = strchr(Variable, '=') + 1;
+ if (Segment == NULL) {
+ continue;
+ }
+
+ //
+ // Convert Segment to lower case.
+ //
+
+ for (i = 0 ; Segment[i] ; i++ ) {
+ Segment[i] = tolower(Segment[i]);
+ }
+
+ //
+ // Look for segments of the type "scsi()disk(x)rdisk()partition(z)"
+ // or "scsi()disk(x)fdisk()" or "scsi()cdrom(x)fdisk()"
+ //
+
+ if (!JzGetPathMnemonicKey( Segment, "scsi", &Key )) {
+ if (!JzGetPathMnemonicKey( Segment, "disk", &Key )) {
+ DeviceId[NumberOfChoices] = Key;
+ if (!JzGetPathMnemonicKey( Segment, "rdisk", &Key )) {
+ if (!JzGetPathMnemonicKey( Segment, "partition", &Key )) {
+ Device[NumberOfChoices] = 0;
+ DevicePartition[NumberOfChoices] = Key;
+ FoundOne = TRUE;
+ }
+ } else if (!JzGetPathMnemonicKey( Segment, "fdisk", &Key )) {
+ Device[NumberOfChoices] = 1;
+ DevicePartition[NumberOfChoices] = 0;
+ FoundOne = TRUE;
+ }
+ } else if (!JzGetPathMnemonicKey( Segment, "cdrom", &Key )) {
+ if (!JzGetPathMnemonicKey( Segment, "fdisk", &Key )) {
+ Device[NumberOfChoices] = 2;
+ DeviceId[NumberOfChoices] = Key;
+ DevicePartition[NumberOfChoices] = 0;
+ FoundOne = TRUE;
+ }
+ }
+ }
+
+ //
+ // Increment number of choices if this is not a duplicate entry.
+ //
+
+ if (FoundOne) {
+ for ( i = 0 ; i < NumberOfChoices ; i++ ) {
+ if ((Device[NumberOfChoices] == Device[i]) &&
+ (DeviceId[NumberOfChoices] == DeviceId[i]) &&
+ (DevicePartition[NumberOfChoices] == DevicePartition[i])) {
+ break;
+ }
+ }
+ if (i == NumberOfChoices) {
+ NumberOfChoices++;
+ if (NumberOfChoices == 10) {
+ break;
+ }
+ }
+ }
+ } while ( More );
+ } while ( !(SecondPass++) && (NumberOfChoices < 10));
+
+ if (NumberOfChoices != 0) {
+
+ //
+ // Make space for the prompt on the screen.
+ //
+
+ JzGoToCurrentLinePosition(1 + NumberOfChoices + 2,
+ CurrentLine,
+ &Line);
+
+ //
+ // Display the choices.
+ //
+
+ VenPrint(SS_SELECT_SYS_PART_MSG);
+
+ for ( Index = 0 ; Index < NumberOfChoices ; Index++ ) {
+ switch (Device[Index]) {
+ case 0:
+ sprintf( MenuItem[Index],
+ SS_SCSI_HD_MSG,
+ DeviceId[Index],
+ DevicePartition[Index]);
+ break;
+ case 1:
+ sprintf( MenuItem[Index],
+ SS_FL_MSG,
+ DeviceId[Index]);
+ break;
+ default:
+ sprintf( MenuItem[Index],
+ SS_SCSI_CD_MSG,
+ DeviceId[Index]);
+ break;
+ }
+ Menu[Index] = MenuItem[Index];
+ }
+
+ strcpy(MenuItem[Index], SS_NEW_SYS_PART_MSG);
+ Menu[Index] = MenuItem[Index];
+
+ Index = JzDisplayMenu(Menu,
+ NumberOfChoices + 1,
+ 0,
+ Line + 1,
+ 0,
+ TRUE);
+
+ if (Index == -1) {
+ return(EINVAL);
+ }
+
+ //
+ // If the user selects new system partition, indicate this by setting
+ // NumberOfChoices to zero.
+ //
+
+ if (Index == NumberOfChoices) {
+ NumberOfChoices = 0;
+ }
+ }
+
+ //
+ // If NumberOfChoices is zero, select a new partition.
+ //
+
+ if (NumberOfChoices == 0) {
+
+ Index = 0;
+
+ //
+ // Make space for the prompt on the screen.
+ //
+
+ JzGoToCurrentLinePosition(2,
+ CurrentLine,
+ &Line);
+
+ //
+ // Determine system partition.
+ //
+
+ VenPrint(SS_LOCATE_SYS_PART_MSG);
+ VenSetPosition(*CurrentLine, 0);
+
+ Device[0] = JzGetDevice(CurrentLine);
+ if (Device[0] == -1) {
+ return(EINVAL);
+ }
+
+ DeviceId[0] = JzGetDeviceId(CurrentLine, Device[0]);
+ if (DeviceId[0] == -1) {
+ return(EINVAL);
+ }
+
+ //
+ // If the media is scsi disk, get the partition.
+ //
+
+ if (Device[0] == 0) {
+ DevicePartition[0] = JzGetPartition(CurrentLine, TRUE);
+ if (DevicePartition[0] == -1) {
+ return(EINVAL);
+ }
+ }
+ }
+
+ //
+ // Create a name string from the Device, DeviceId,
+ // DevicePartition.
+ //
+
+ switch (Device[Index]) {
+ case 0:
+ sprintf( SystemPartition,
+ "scsi()disk(%1d)rdisk()partition(%1d)",
+ DeviceId[Index],
+ DevicePartition[Index]);
+ break;
+ case 1:
+ sprintf( SystemPartition,
+ FW_FLOPPY_0_FORMAT_DEVICE,
+ DeviceId[Index]);
+ break;
+ default:
+ sprintf( SystemPartition,
+ "scsi()cdrom(%1d)fdisk()",
+ DeviceId[Index]);
+ break;
+ }
+
+ return(ESUCCESS);
+}
+
+
+
+#ifdef ISA_PLATFORM
+
+ULONG
+JzGetScsiId (
+ IN PULONG CurrentLine,
+ IN PCHAR Prompt,
+ IN ULONG InitialValue
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG Line;
+ ULONG ReturnValue;
+ CHAR TempString[5];
+ GETSTRING_ACTION Action;
+
+ //
+ // Make space for the prompt on the screen.
+ //
+
+ JzGoToCurrentLinePosition(1,
+ CurrentLine,
+ &Line);
+
+ while (TRUE) {
+ VenSetPosition( Line, 0);
+
+ VenPrint(Prompt);
+ VenPrint("\x9bK");
+
+ sprintf(TempString, "%1d", InitialValue);
+
+ do {
+ Action = JzGetString( TempString,
+ sizeof(TempString),
+ TempString,
+ Line,
+ strlen(Prompt) + 1,
+ TRUE);
+
+ if (Action == GetStringEscape) {
+ return(-1);
+ }
+
+ } while ( Action != GetStringSuccess );
+
+ ReturnValue = atoi(TempString);
+
+ if ((ReturnValue >= 0) && (ReturnValue <= 7)) {
+ break;
+ }
+ }
+
+ VenSetPosition( *CurrentLine, 0);
+ return ReturnValue;
+}
+
+#endif
+
+
+
+BOOLEAN
+JzMakeDefaultConfiguration (
+ IN BOOLEAN DoFactoryDefaults
+ )
+
+/*++
+
+Routine Description:
+
+ This loads a default Alpha/Jensen configuration into both the
+ volatile and non-volatile areas.
+
+ Because Jensen has an FEPROM, this function must read the PROM, clear
+ the block, and then write just the environment variables back. The
+ code to do this is lifted from fw\alpha\jxconfig.c.
+
+Arguments:
+
+ DoFactoryDefaults If TRUE, reset the configuration area to
+ factory defaults and do not prompt the user
+ for anything.
+
+Return Value:
+
+ Returns TRUE if the configuration was modified, otherwise returns FALSE.
+
+--*/
+{
+ ARC_STATUS Status;
+ ULONG Index;
+ UCHAR Character;
+ ULONG Count;
+ PUCHAR Nvram;
+ ULONG CurrentLine;
+ LONG Monitor;
+ LONG Floppy;
+ LONG Floppy2;
+ ULONG OldScsiHostId;
+
+ VenClearScreen();
+ JzShowTime(TRUE);
+ CurrentLine = 3;
+
+#ifdef ISA_PLATFORM
+
+ if (DoFactoryDefaults) {
+
+ Monitor = 0;
+ Floppy = 2;
+ Floppy2 = -1;
+ ScsiHostId = 7;
+
+ } else {
+
+ Monitor = JzGetMonitor(&CurrentLine);
+ if (Monitor == -1) {
+ return(FALSE);
+ }
+
+ Floppy = JzGetFloppy(&CurrentLine);
+ if (Floppy == -1) {
+ return(FALSE);
+ }
+
+ Floppy2 = JzGetYesNo(&CurrentLine, SS_2ND_FLOPPY_MSG, FALSE);
+ if (Floppy2 == -1) {
+ return(FALSE);
+ }
+
+ if (Floppy2 == 0) {
+ Floppy2 = JzGetFloppy(&CurrentLine);
+ if (Floppy == -1) {
+ return(FALSE);
+ }
+ } else {
+ Floppy2 = -1;
+ }
+
+ //
+ // Save the current scsi host id, and then change ScsiHostId to an
+ // invalid value so that the user can select the current id (see
+ // JzGetScsiId).
+ //
+
+ OldScsiHostId = ScsiHostId;
+ ScsiHostId = 8;
+ ScsiHostId = JzGetScsiId(&CurrentLine,
+ SS_SCSI_HOST_MSG,
+ OldScsiHostId);
+ if (ScsiHostId == -1) {
+ ScsiHostId = OldScsiHostId;
+ return(FALSE);
+ }
+
+
+ }
+#else
+
+ if (DoFactoryDefaults) {
+
+ Floppy = 2;
+ Floppy2 = -1;
+
+ } else {
+
+ Floppy = JzGetFloppy(&CurrentLine);
+ if (Floppy == -1) {
+ return(FALSE);
+ }
+
+ Floppy2 = JzGetYesNo(&CurrentLine, SS_2ND_FLOPPY_MSG, FALSE);
+ if (Floppy2 == -1) {
+ return(FALSE);
+ }
+
+ if (Floppy2 == 0) {
+ Floppy2 = JzGetFloppy(&CurrentLine);
+ if (Floppy == -1) {
+ return(FALSE);
+ }
+ } else {
+ Floppy2 = -1;
+ }
+
+ }
+
+#endif
+
+ //
+ // Clear the configuration tree information in the Volatile area.
+ //
+
+ RtlZeroMemory(Configuration, sizeof(CONFIGURATION));
+ SetupROMPendingModified = TRUE;
+
+ //
+ // Add components.
+ //
+
+ JzMakeConfiguration(Monitor, Floppy, Floppy2);
+
+ return(TRUE);
+}
+
+
+BOOLEAN
+JzMakeDefaultEnvironment (
+ IN BOOLEAN DoFactoryDefaults
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+ DoFactoryDefaults If TRUE, reset the configuration area to
+ factory defaults and do not prompt the user
+ for anything.
+Return Value:
+
+ Returns TRUE if the ROM has a pending change. Otherwise, FALSE.
+
+--*/
+{
+ ARC_STATUS Status;
+ ULONG Index;
+ UCHAR Character;
+ ULONG Count;
+ PUCHAR Nvram;
+ ULONG CurrentLine;
+ LONG Device;
+ LONG DeviceId;
+ LONG DevicePartition;
+
+
+ //
+ // If resetting to factory defaults, continue printing out at whereever
+ // the cursor is on the screen.
+ //
+
+ if (DoFactoryDefaults) {
+
+ Device = 0;
+ DeviceId = 0;
+ DevicePartition = 1;
+
+ } else {
+
+ VenClearScreen();
+ JzShowTime(TRUE);
+ CurrentLine = 3;
+ VenSetPosition(3,0);
+
+ VenPrint(SS_DEFAULT_SYS_PART_MSG);
+ CurrentLine += 2;
+ VenSetPosition( CurrentLine, 0);
+
+ Device = JzGetDevice(&CurrentLine);
+ if (Device == -1) {
+ return (FALSE);
+ }
+
+ DeviceId = JzGetDeviceId(&CurrentLine, Device);
+ if (DeviceId == -1) {
+ return (FALSE);
+ }
+
+ //
+ // If the media is scsi disk, get the partition.
+ //
+
+ if (Device == 0) {
+ DevicePartition = JzGetPartition(&CurrentLine, TRUE);
+ if (DevicePartition == -1) {
+ return (FALSE);
+ }
+
+ }
+ }
+
+
+ //
+ // Clear the environment information in the volatile area.
+ //
+
+ RtlZeroMemory(VolatileEnvironment, LENGTH_OF_ENVIRONMENT);
+ SetupROMPendingModified = TRUE;
+
+ //
+ // Add environment variables.
+ //
+
+ JzMakeEnvironment(Device, DeviceId, DevicePartition);
+
+ return (TRUE);
+}
+
+
+VOID
+JzDeleteVariableSegment (
+ PCHAR VariableName,
+ ULONG Selection
+ )
+
+/*++
+
+Routine Description:
+
+ This works on the volatile copy of a segmented environment variable.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PCHAR Variable;
+ CHAR VariableValue[MAXIMUM_ENVIRONMENT_VALUE];
+ ULONG Index;
+ ULONG Count;
+ BOOLEAN FirstSegment;
+
+ if ((Variable = FwGetVolatileEnvironmentVariable(VariableName)) == NULL) {
+ return;
+ }
+
+ FirstSegment = TRUE;
+ Index = 0;
+ *VariableValue = 0;
+
+ while (strchr(Variable,';') != NULL) {
+
+ Count = strchr(Variable,';') - Variable;
+
+ if (Index != Selection) {
+
+ if (!FirstSegment) {
+ strcat(VariableValue,";");
+ }
+
+ strncat(VariableValue, Variable, Count);
+ FirstSegment = FALSE;
+ }
+
+ Variable += Count + 1;
+ Index++;
+ }
+
+ if (Index != Selection) {
+ if (!FirstSegment) {
+ strcat(VariableValue,";");
+ }
+ strcat(VariableValue,Variable);
+ }
+
+ SetupROMPendingModified = TRUE;
+ FwCoreSetEnvironmentVariable(VariableName, VariableValue, FALSE);
+ return;
+}
+
+VOID
+JzAddBootSelection (
+ IN BOOLEAN DoFactoryDefaults
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+ DoFactoryDefaults If TRUE, reset the configuration area to
+ factory defaults and do not prompt the user
+ for anything.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ARC_STATUS Status;
+ CHAR SystemPartition[128];
+ CHAR OsloaderFilename[80];
+ CHAR OsPartition[128];
+ CHAR OsFilename[80];
+ CHAR LoadIdentifier[80];
+ PCHAR Variable;
+ PCHAR TempPointer;
+ CHAR VariableValue[256];
+ ULONG Index;
+ UCHAR Character;
+ ULONG Count;
+ ULONG CurrentLine;
+ ULONG Line;
+ LONG Device;
+ LONG DeviceId;
+ LONG DevicePartition;
+ LONG YesNo;
+ BOOLEAN DebugOn;
+ GETSTRING_ACTION Action;
+ BOOLEAN SecondaryBoot;
+
+
+ if (!DoFactoryDefaults) {
+ VenClearScreen();
+ JzShowTime(TRUE);
+ CurrentLine = 3;
+ VenSetPosition( CurrentLine, 0);
+ }
+
+ //
+ // Count the boot selections
+ //
+
+ strcpy(OsPartition, BootString[OsLoadPartitionVariable]);
+ strcpy(OsFilename, BootString[OsLoadFilenameVariable]);
+
+ for ( Index = 0 ; Index < 4 ; Index++ ) {
+
+ SecondaryBoot = FwGetVariableSegment(Index, OsPartition);
+ SecondaryBoot = FwGetVariableSegment(Index, OsFilename) ||
+ SecondaryBoot;
+
+ if (!SecondaryBoot) {
+ break;
+ }
+ }
+
+ //
+ // Increment to new boot selection. Print warning and return if too many.
+ //
+
+ Index++;
+ if (Index == 5) {
+ VenPrint(SS_TOO_MANY_BOOT_SELECTIONS);
+ FwWaitForKeypress(TRUE);
+ return;
+ }
+
+ if (DoFactoryDefaults) {
+
+ strcpy(SystemPartition, "scsi()disk()rdisk()partition(1)");
+ strcpy(OsloaderFilename, "\\os\\nt\\osloader.exe");
+ strcpy(OsPartition, "scsi()disk()rdisk()partition(2)");
+ strcpy(OsFilename, "\\winnt");
+
+#ifdef ALPHA_FW_KDHOOKS
+ DebugOn = TRUE;
+#else
+ DebugOn = FALSE;
+#endif
+
+ strcpy(LoadIdentifier, "Windows NT");
+
+ } else {
+
+ //
+ // Pick a system partition.
+ //
+
+ if (JzPickSystemPartition(SystemPartition, &CurrentLine) != ESUCCESS) {
+ return;
+ }
+
+ //
+ // Make space for the prompt on the screen.
+ //
+
+ JzGoToCurrentLinePosition(2,
+ &CurrentLine,
+ &Line);
+
+ VenPrint(SS_CRLF_MSG);
+ VenPrint(SS_OSLOADER_MSG);
+
+ do {
+ Action = JzGetString( OsloaderFilename,
+ sizeof(OsloaderFilename),
+ "\\os\\nt\\osloader.exe",
+ Line + 1,
+ strlen(SS_OSLOADER_MSG),
+ TRUE);
+ if (Action == GetStringEscape) {
+ return;
+ }
+ } while ( Action != GetStringSuccess );
+
+ CurrentLine++;
+
+ YesNo = JzGetYesNo(&CurrentLine,
+ SS_OS_MSG,
+ TRUE);
+
+ if (YesNo == -1) {
+ return;
+ }
+
+ if (YesNo == 0) {
+ strcpy(OsPartition, SystemPartition);
+ } else {
+
+ //
+ // Determine os partition.
+ //
+
+ VenPrint(SS_LOCATE_OS_PART_MSG);
+ CurrentLine += 1;
+
+ Device = JzGetDevice(&CurrentLine);
+ if (Device == -1) {
+ return;
+ }
+
+ DeviceId = JzGetDeviceId(&CurrentLine, Device);
+ if (DeviceId == -1) {
+ return;
+ }
+
+ //
+ // If the media is scsi disk, get the partition.
+ //
+
+ if (Device == 0) {
+ DevicePartition = JzGetPartition(&CurrentLine, FALSE);
+ if (DevicePartition == -1) {
+ return;
+ }
+ }
+
+ //
+ // Create a name string from the Device, DeviceId,
+ // DevicePartition.
+ //
+
+ if (Device != 1) {
+ sprintf( OsPartition,
+ "scsi()disk(%1d)rdisk()partition(%1d)",
+ DeviceId,
+ DevicePartition);
+ } else {
+ sprintf( OsPartition,
+ "scsi()cdrom(%1d)fdisk()",
+ DeviceId);
+ }
+
+ CurrentLine++;
+ }
+
+ //
+ // Make space for the prompt on the screen.
+ //
+
+ JzGoToCurrentLinePosition(2,
+ &CurrentLine,
+ &Line);
+
+ VenPrint(SS_OS_ROOT_MSG);
+
+ do {
+ Action = JzGetString( OsFilename,
+ sizeof(OsFilename),
+ "\\winnt",
+ Line,
+ strlen(SS_OS_ROOT_MSG),
+ TRUE);
+ if (Action == GetStringEscape) {
+ return;
+ }
+ } while ( Action != GetStringSuccess );
+
+ //
+ // Make space for the prompts on the screen.
+ //
+
+ JzGoToCurrentLinePosition(2,
+ &CurrentLine,
+ &Line);
+
+ VenPrint(SS_BOOT_NAME_MSG);
+
+ do {
+ Action = JzGetString( LoadIdentifier,
+ sizeof(LoadIdentifier),
+ "Windows NT ",
+ Line,
+ strlen(SS_BOOT_NAME_MSG),
+ TRUE);
+ if (Action == GetStringEscape) {
+ return;
+ }
+ } while ( Action != GetStringSuccess );
+
+ YesNo = JzGetYesNo(&CurrentLine, SS_INIT_DEBUG_MSG, FALSE);
+
+ if (YesNo == -1) {
+ return;
+ }
+
+ if (YesNo == 0) {
+ DebugOn = TRUE;
+ } else {
+ DebugOn = FALSE;
+ }
+ }
+
+
+ SetupROMPendingModified = TRUE;
+
+ //
+ // Now add in the boot selection.
+ //
+
+ Index = 0;
+ Status = FwSetVariableSegment(0, BootString[LoadIdentifierVariable], LoadIdentifier);
+ if (Status != ESUCCESS) {
+ goto MakeError;
+ }
+
+
+ Index = 1;
+
+ //
+ // If the SystemPartition variable is set but the Osloader variable is null,
+ // clear the SystemPartition variable before adding it back.
+ //
+
+ if ((FwGetVolatileEnvironmentVariable(BootString[SystemPartitionVariable]) != NULL) &&
+ (FwGetVolatileEnvironmentVariable(BootString[OsLoaderVariable]) == NULL)) {
+ FwCoreSetEnvironmentVariable(BootString[SystemPartitionVariable],
+ "",
+ FALSE);
+ }
+
+ Status = FwSetVariableSegment(0,
+ BootString[SystemPartitionVariable],
+ SystemPartition);
+
+ if (Status != ESUCCESS) {
+ goto MakeError;
+ }
+
+ //
+ // Add a new selection to the OSLOADER environment variable.
+ //
+
+ Index = 2;
+ strcpy(VariableValue, SystemPartition);
+ strcat(VariableValue, OsloaderFilename);
+ Status = FwSetVariableSegment(0, BootString[OsLoaderVariable], VariableValue);
+
+ if (Status != ESUCCESS) {
+ goto MakeError;
+ }
+
+
+ //
+ // Add a new selection to the OSLOADPARTITION environment variable.
+ //
+
+ Index = 3;
+ Status = FwSetVariableSegment(0, BootString[OsLoadPartitionVariable], OsPartition);
+ if (Status != ESUCCESS) {
+ goto MakeError;
+ }
+
+ //
+ // Add a new selection to the OSLOADFILENAME environment variable.
+ //
+
+ Index = 4;
+ Status = FwSetVariableSegment(0, BootString[OsLoadFilenameVariable], OsFilename);
+ if (Status != ESUCCESS) {
+ goto MakeError;
+ }
+
+
+ //
+ // Add a new selection to the OSLOADOPTIONS environment variable.
+ //
+
+ if (DebugOn) {
+ strcpy(VariableValue, "debug");
+ } else {
+ strcpy(VariableValue, "nodebug");
+ }
+
+ Index = 5;
+ Status = FwSetVariableSegment(0, BootString[OsLoadOptionsVariable], VariableValue);
+ if (Status != ESUCCESS) {
+ goto MakeError;
+ }
+
+ return;
+
+
+MakeError:
+
+ VenPrint(SS_CANT_SET_VARIABLE_MSG);
+
+ //
+ // Delete any segments that were added.
+ //
+
+ for ( Count = 0 ; Count < Index ; Count++ ) {
+ JzDeleteVariableSegment(BootString[Count], 0);
+ }
+
+ FwWaitForKeypress(TRUE);
+}
+
+
+LONG
+JzPickBootSelection (
+ IN OUT PULONG CurrentLine,
+ IN PCHAR PromptString
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allows the user to indicate a boot selection choice.
+
+Arguments:
+
+ CurrentLine - Supplies a pointer to the current display line value.
+
+ PromptString - Supplies a pointer to a string which indicates the reason
+ the boot selection choice is needed.
+
+Return Value:
+
+ Returns the boot selection number, -1 if none.
+
+--*/
+{
+ PCHAR Variable;
+ CHAR VariableValue[MAXIMUM_ENVIRONMENT_VALUE];
+ CHAR BootChoices[5][128];
+ PCHAR BootMenu[5];
+ ULONG Line;
+ CHAR OsloadPartition[128];
+ CHAR OsloadFilename[128];
+ CHAR LoadIdentifier[80];
+ BOOLEAN SecondaryBoot;
+ ULONG Index;
+ ULONG Selection;
+
+ //
+ // Get each boot selection
+ //
+
+ strcpy(OsloadPartition, BootString[OsLoadPartitionVariable]);
+ strcpy(OsloadFilename, BootString[OsLoadFilenameVariable]);
+ strcpy(LoadIdentifier, BootString[LoadIdentifierVariable]);
+
+ for ( Index = 0 ; ; Index++ ) {
+
+ SecondaryBoot = FwGetVariableSegment(Index, OsloadPartition);
+ SecondaryBoot = FwGetVariableSegment(Index, OsloadFilename) ||
+ SecondaryBoot;
+ SecondaryBoot = FwGetVariableSegment(Index, LoadIdentifier) ||
+ SecondaryBoot;
+
+ if (LoadIdentifier[sizeof("LOADIDENTIFIER=") - 1] != 0) {
+ strcpy(BootChoices[Index],
+ &LoadIdentifier[sizeof("LOADIDENTIFIER=") - 1]);
+ } else {
+ strcpy(BootChoices[Index],
+ &OsloadPartition[sizeof("OsloadPartition=") - 1]);
+ strcat(BootChoices[Index],
+ &OsloadFilename[sizeof("OsloadFilename=") - 1]);
+ }
+
+ BootMenu[Index] = BootChoices[Index];
+
+ if (!SecondaryBoot || (Index == 4)) {
+ break;
+ }
+ }
+
+ VenPrint(PromptString);
+
+ //
+ // Make space for the prompt on the screen.
+ //
+
+ JzGoToCurrentLinePosition(Index + 1 + 1,
+ CurrentLine,
+ &Line);
+
+ Selection = JzDisplayMenu( BootMenu,
+ Index + 1,
+ 0,
+ Line + 1,
+ 0,
+ TRUE);
+
+ VenSetPosition(*CurrentLine, 0);
+
+ return(Selection);
+}
+
+
+VOID
+JzDeleteBootSelection (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine deletes a boot selection from the boot environment variables.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ARC_STATUS Status;
+ ULONG CurrentLine;
+ LONG Selection;
+ ULONG Index;
+
+ VenClearScreen();
+ JzShowTime(TRUE);
+ CurrentLine = 3;
+ VenSetPosition( CurrentLine, 0);
+
+ if (FwGetVolatileEnvironmentVariable(BootString[OsLoadPartitionVariable]) == NULL) {
+ VenPrint(SS_NO_SELECTIONS_TO_DELETE_MSG);
+ CurrentLine += 1;
+ FwWaitForKeypress(TRUE);
+ return;
+ }
+
+ Selection = JzPickBootSelection( &CurrentLine, SS_SELECTION_TO_DELETE_MSG);
+
+ if (Selection == -1) {
+ return;
+ }
+
+ //
+ // The requested boot selection will now be deleted. The systempartition
+ // variable is not deleted if there is only one segment left, so that
+ // deleting the last boot selection leaves the NVRAM in the same
+ // state as an initial set default environment.
+ //
+
+ for ( Index = 0 ; Index < MaximumBootVariable ; Index++ ) {
+
+ if ((Index == SystemPartitionVariable) &&
+ (FwGetVolatileEnvironmentVariable(BootString[Index]) != NULL) &&
+ (strchr(FwGetVolatileEnvironmentVariable(BootString[Index]), ';') == NULL)) {
+ continue;
+ }
+
+ JzDeleteVariableSegment(BootString[Index],Selection);
+ }
+
+ return;
+}
+
+VOID
+JzEditSelection (
+ LONG Selection
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allows the environment variables for a specified boot
+ selection to be edited.
+
+Arguments:
+
+ Selection - Specifies the boot selection to edit.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ARC_STATUS Status;
+ CHAR SystemPartition[128];
+ CHAR Osloader[128];
+ CHAR OsloadPartition[128];
+ CHAR OsloadFilename[128];
+ CHAR OsloadOptions[128];
+ CHAR LoadIdentifier[128];
+
+ SetupROMPendingModified = TRUE;
+
+ do {
+ VenClearScreen();
+ JzShowTime(TRUE);
+ VenSetPosition( 7, 0);
+
+ //
+ // Display the current boot selection environment variables.
+ //
+
+ strcpy(SystemPartition, BootString[SystemPartitionVariable]);
+ strcpy(Osloader, BootString[OsLoaderVariable]);
+ strcpy(OsloadPartition, BootString[OsLoadPartitionVariable]);
+ strcpy(OsloadFilename, BootString[OsLoadFilenameVariable]);
+ strcpy(OsloadOptions, BootString[OsLoadOptionsVariable]);
+ strcpy(LoadIdentifier, BootString[LoadIdentifierVariable]);
+ FwGetVariableSegment(Selection, SystemPartition);
+ FwGetVariableSegment(Selection, Osloader);
+ FwGetVariableSegment(Selection, OsloadPartition);
+ FwGetVariableSegment(Selection, OsloadFilename);
+ FwGetVariableSegment(Selection, OsloadOptions);
+ FwGetVariableSegment(Selection, LoadIdentifier);
+
+ VenPrint1(SS_ENVIR_FOR_BOOT_MSG, Selection + 1);
+
+ VenPrint1(SS_FORMAT1_MSG, LoadIdentifier);
+ VenPrint1(SS_FORMAT1_MSG, SystemPartition);
+ VenPrint1(SS_FORMAT1_MSG, Osloader);
+ VenPrint1(SS_FORMAT1_MSG, OsloadPartition);
+ VenPrint1(SS_FORMAT1_MSG, OsloadFilename);
+ VenPrint1(SS_FORMAT1_MSG, OsloadOptions);
+
+ VenSetPosition( 2, 0);
+ VenPrint(SS_USE_ARROWS_MSG);
+
+ } while ( JzSetBootEnvironmentVariable(Selection) );
+
+ return;
+}
+
+VOID
+JzEditBootSelection (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allows the environment variables for a boot selection to
+ be edited.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ARC_STATUS Status;
+ ULONG CurrentLine;
+ LONG Selection;
+
+ VenClearScreen();
+ JzShowTime(TRUE);
+ CurrentLine = 3;
+ VenSetPosition( CurrentLine, 0);
+
+ if (FwGetVolatileEnvironmentVariable("OsloadPartition") == NULL) {
+ VenPrint(SS_NO_SELECTIONS_TO_EDIT_MSG);
+ CurrentLine += 1;
+ FwWaitForKeypress(TRUE);
+ return;
+ }
+
+ Selection = JzPickBootSelection( &CurrentLine, SS_SELECTION_TO_EDIT_MSG);
+
+ if (Selection == -1) {
+ return;
+ }
+
+ JzEditSelection(Selection);
+
+ return;
+}
+
+VOID
+JzRearrangeBootSelections (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allows the environment variables for a boot selection to
+ be rearranged.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ARC_STATUS Status;
+ ULONG CurrentLine;
+ LONG Selection;
+ ULONG Index;
+ CHAR Segment[128];
+
+ VenClearScreen();
+ JzShowTime(TRUE);
+ CurrentLine = 3;
+ VenSetPosition( CurrentLine, 0);
+
+ if (FwGetVolatileEnvironmentVariable("OsloadPartition") == NULL) {
+ VenPrint(SS_NO_SELECTIONS_TO_REARRANGE_MSG);
+ CurrentLine += 1;
+ FwWaitForKeypress(TRUE);
+ return;
+ }
+
+ SetupROMPendingModified = TRUE;
+
+ do {
+ VenClearScreen();
+ JzShowTime(TRUE);
+ CurrentLine = 3;
+ VenSetPosition( CurrentLine, 0);
+
+ Selection = JzPickBootSelection( &CurrentLine, SS_PICK_SELECTION_MSG);
+
+ if (Selection == -1) {
+ continue;
+ }
+
+ for ( Index = 0 ; Index < MaximumBootVariable ; Index++ ) {
+ strcpy( Segment, BootString[Index]);
+ FwGetVariableSegment( Selection, Segment );
+ JzDeleteVariableSegment( BootString[Index], Selection );
+ FwSetVariableSegment( 0, BootString[Index], strchr(Segment, '=') + 1);
+ }
+ } while ( Selection != -1 );
+ return;
+}
+
+
+VOID
+JzSetupAutoboot (
+ IN BOOLEAN DoFactoryDefaults
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allows the environment variables controlling autoboot
+ to be set.
+
+Arguments:
+
+ DoFactoryDefaults If TRUE, reset to factory defaults and do
+ not prompt the user for anything.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ARC_STATUS Status;
+ ULONG Autoboot;
+ ULONG Countdown;
+ CHAR CountdownString[5];
+ ULONG CurrentLine;
+
+
+ if (DoFactoryDefaults) {
+
+ Autoboot = 0;
+
+ } else {
+
+ VenClearScreen();
+ JzShowTime(TRUE);
+ CurrentLine = 3;
+
+ Autoboot = JzGetYesNo(&CurrentLine,
+ SS_SHOULD_AUTOBOOT_MSG,
+ TRUE);
+ if (Autoboot == -1) {
+ return;
+ }
+
+ }
+
+ SetupROMPendingModified = TRUE;
+
+ switch (Autoboot) {
+ case 0:
+ Status = FwCoreSetEnvironmentVariable("AUTOLOAD", "YES", FALSE);
+ break;
+ default:
+ Status = FwCoreSetEnvironmentVariable("AUTOLOAD", "NO", FALSE);
+ break;
+ }
+
+ if (Status != ESUCCESS) {
+ VenPrint(SS_CANT_SET_VARIABLE_MSG);
+ return;
+ }
+
+ if (Autoboot != 0) {
+ return;
+ }
+
+
+ if (DoFactoryDefaults) {
+ Countdown = 10;
+ } else {
+
+ Countdown = JzGetCountdownValue(&CurrentLine);
+
+ if (Countdown == -1) {
+ return;
+ }
+
+ if (Countdown == 0) {
+ Countdown = 1;
+ }
+ }
+
+
+ sprintf( CountdownString, "%d", Countdown);
+
+ Status = FwCoreSetEnvironmentVariable("COUNTDOWN", CountdownString, FALSE);
+
+ if (Status != ESUCCESS) {
+ VenPrint(SS_CANT_SET_VARIABLE_MSG);
+ }
+
+ return;
+}
+
+
+VOID
+JzEditVariable (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allows environment variables to be edited.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ARC_STATUS Status;
+ PCHAR Variable;
+ ULONG Index, Count;
+
+
+ SetupROMPendingModified = TRUE;
+
+ do {
+
+ VenClearScreen();
+ JzShowTime(TRUE);
+ VenSetPosition( 9, 0);
+
+ //
+ // Get the entire environment.
+ //
+
+ Variable = VolatileEnvironment;
+
+ VenPrint(SS_ENVIRONMENT_VARS_MSG);
+
+ if (Variable != NULL) {
+
+ //
+ // Print all of the other environment variables.
+ //
+
+ while (*Variable) {
+
+ if ((strstr(Variable, "SYSTEMPARTITION=") == NULL) &&
+ (strstr(Variable, "OSLOADER=") == NULL) &&
+ (strstr(Variable, "OSLOADPARTITION=") == NULL) &&
+ (strstr(Variable, "OSLOADFILENAME=") == NULL) &&
+ (strstr(Variable, "OSLOADOPTIONS=") == NULL) &&
+ (strstr(Variable, "LOADIDENTIFIER=") == NULL)) {
+
+ VenPrint(" ");
+ while (strchr(Variable,';') != NULL) {
+ Index = strchr(Variable,';') - Variable + 1;
+ ArcWrite(ARC_CONSOLE_OUTPUT, Variable, Index, &Count);
+ VenPrint("\r\n ");
+ Variable += Index;
+ }
+ VenPrint(Variable);
+ VenPrint(SS_CRLF_MSG);
+ }
+ Variable = strchr(Variable,'\0') + 1;
+ }
+ }
+
+ VenSetPosition( 3, 0);
+ VenPrint(SS_USE_ARROWS_MSG);
+
+ } while ( JzSetEnvironmentVariable() );
+ return;
+}
+
+BOOLEAN
+JzCheckBootSelection (
+ IN LONG Selection,
+ IN BOOLEAN Silent,
+ OUT PBOOLEAN FoundProblems
+ )
+
+/*++
+
+Routine Description:
+
+ This routine checks the integrity of a volatile boot selection.
+
+Arguments:
+
+ Selection - The number of the selection to check.
+
+ Silent - True if this should run silently.
+
+ FoundProblems - Or'd with TRUE if there was at least one problem.
+
+
+Return Value:
+
+ Returns TRUE if there are more selections after the current one, otherwise
+ returns FALSE.
+
+--*/
+{
+ ARC_STATUS Status;
+ ULONG CurrentLine;
+ ULONG Fid;
+ ULONG MenuSelection;
+ ULONG Index;
+ CHAR BootSelectionIdentifier[80];
+ CHAR Segment[128];
+ CHAR Value[128];
+ BOOLEAN MoreSelections;
+ BOOLEAN Problem;
+
+ //
+ // Get the name of this boot selection, if it exists.
+ //
+
+ strcpy (BootSelectionIdentifier, BootString[LoadIdentifierVariable]);
+ FwGetVariableSegment(Selection, BootSelectionIdentifier);
+ strcpy (BootSelectionIdentifier, strchr(BootSelectionIdentifier, '=') + 1);
+
+ if (!Silent) {
+ VenClearScreen();
+ VenSetPosition( 3, 0);
+ VenPrint(SS_CHECKING_MSG);
+ if (BootSelectionIdentifier[0] == 0) {
+ VenPrint1(SS_CHECKING_BOOT_SEL_NUMBER_MSG, Selection);
+ } else {
+ VenPrint1(SS_FORMAT2_MSG, BootSelectionIdentifier);
+ }
+
+ CurrentLine = 6 + NUMBER_OF_PROBLEMS;
+ VenSetPosition( CurrentLine, 0);
+ }
+
+ MoreSelections = FALSE;
+ Problem = FALSE;
+
+ if (!Silent) {
+ VenSetScreenColor( ArcColorYellow, ArcColorBlue);
+ }
+
+ for ( Index = 0 ; Index < MaximumBootVariable ; Index++ ) {
+
+ strcpy(Segment, BootString[Index]);
+ MoreSelections = FwGetVariableSegment(Selection, Segment) || MoreSelections;
+ strcpy(Value, strchr(Segment, '=') + 1);
+
+ //
+ // Check to make sure the value is not NULL, except for OsloadOptions
+ // which can legally have a NULL value.
+ //
+
+ if ((Index != OsLoadOptionsVariable) && (Value[0] == 0)) {
+ if (Silent) {
+ *FoundProblems = TRUE;
+ return (FALSE);
+ }
+ Problem = TRUE;
+ VenPrint1(SS_VARIABLE_NULL_MSG, BootString[Index]);
+ continue;
+ }
+
+ //
+ // If this is the SystemPartition, Osloader, or OsloadPartition
+ // variable, check to make sure it can be opened.
+ //
+
+ if ((Index == SystemPartitionVariable) ||
+ (Index == OsLoaderVariable) ||
+ (Index == OsLoadPartitionVariable) ) {
+
+ if (ArcOpen(Value, ArcOpenReadOnly, &Fid) != ESUCCESS) {
+ if (Silent) {
+ *FoundProblems = TRUE;
+ return (FALSE);
+ }
+ Problem = TRUE;
+ VenPrint1( SS_CANT_BE_FOUND_MSG, BootString[Index]);
+ VenPrint1( SS_FORMAT1_MSG, Value);
+ } else {
+ ArcClose(Fid);
+ }
+
+ }
+ }
+
+ //
+ // If we are running silently and have gotten to here, there were no
+ // problems and we can return now.
+ //
+
+ if (Silent) {
+ return (MoreSelections);
+ }
+
+ //
+ // We are not running in silent mode. If there were problems, query the
+ // user.
+ //
+
+ VenSetScreenColor( ArcColorWhite, ArcColorBlue);
+
+ if (Problem) {
+
+ JzShowTime(TRUE);
+ CurrentLine = 3;
+ VenSetPosition( CurrentLine, 0);
+
+ VenPrint(SS_PROBLEMS_FOUND_MSG);
+ if (BootSelectionIdentifier[0] == 0) {
+ VenPrint1(SS_CHECKING_BOOT_SEL_NUMBER_MSG, Selection);
+ } else {
+ VenPrint1(SS_FORMAT2_MSG, BootSelectionIdentifier);
+ }
+ VenPrint(SS_PROBLEMS_CHOOSE_AN_ACTION_MSG);
+
+ MenuSelection = JzDisplayMenu( ProblemChoices,
+ NUMBER_OF_PROBLEMS,
+ 0,
+ CurrentLine + 2,
+ 0,
+ TRUE);
+
+ //
+ // Switch based on the action.
+ //
+
+ switch (MenuSelection) {
+
+ //
+ // Ignore
+ //
+
+ case 0:
+ break;
+
+ //
+ // Delete this boot selection
+ //
+
+ case 1:
+
+ for ( Index = 0 ; Index < MaximumBootVariable ; Index++ ) {
+ JzDeleteVariableSegment(BootString[Index],Selection);
+ }
+ break;
+
+ //
+ // Edit this boot selection
+ //
+
+ case 2:
+ JzEditSelection(Selection);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return(MoreSelections);
+}
+
+
+VOID
+JzCheckBootSelections (
+ IN BOOLEAN Silent,
+ OUT PBOOLEAN FoundProblems
+ )
+
+/*++
+
+Routine Description:
+
+ This routine cycles through all of the volatile boot selections and
+ checks them.
+
+Arguments:
+
+ Silent - True if this should run silently.
+
+ FoundProblems - Returns TRUE if there was at least one problem.
+ Otherwise, returns FALSE.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG Index;
+
+ *FoundProblems = FALSE;
+
+ //
+ // Look to see if any boot selections exist. Skip the SystemPartition
+ // variable because that can be set without any selections.
+ //
+
+ for ( Index = 0 ; Index < MaximumBootVariable ; Index++ ) {
+ if ( (Index != SystemPartitionVariable) &&
+ (FwGetVolatileEnvironmentVariable(BootString[Index]) != NULL)) {
+ break;
+ }
+ }
+
+ //
+ // If there are boot selections, check them.
+ //
+
+ if (Index != MaximumBootVariable) {
+ Index = 0;
+ while (JzCheckBootSelection(Index, Silent, FoundProblems)) {
+ Index++;
+ }
+ }
+ return;
+}
diff --git a/private/ntos/fw/alpha/jnsetset.c b/private/ntos/fw/alpha/jnsetset.c
new file mode 100644
index 000000000..bc3ba1436
--- /dev/null
+++ b/private/ntos/fw/alpha/jnsetset.c
@@ -0,0 +1,1007 @@
+/*++
+
+Copyright (c) 1991, 1992 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ jnsetset.c
+
+
+Abstract:
+
+ A firmware tool that allows the user to examine and
+ modify the Alpha/Jensen PROM data.
+
+
+Author:
+
+ John DeRosa 31-July-1992.
+
+ This module, and the entire setup program, was based on the jzsetup
+ program written by David M. Robinson (davidro) of Microsoft, dated
+ 9-Aug-1991.
+
+
+Revision History:
+
+--*/
+
+#include "fwp.h"
+#include "jnsnvdeo.h"
+#include "machdef.h"
+
+#ifdef JENSEN
+#include "jnsnrtc.h"
+#else
+#include "mrgnrtc.h" // morgan
+#endif
+
+#include "string.h"
+#include "iodevice.h"
+#include "jnvendor.h"
+#include "fwstring.h"
+#include "xxstring.h"
+
+//
+// Routine prototypes.
+//
+
+VOID
+FwOperatingSystemSwitch(
+ VOID
+ );
+
+VOID
+JzDumpBootSelections(
+ VOID
+ );
+
+BOOLEAN
+JzBootMenu(
+ VOID
+ );
+
+VOID
+JzEnvironmentMenu(
+ VOID
+ );
+
+VOID
+JzUpdateROMData(
+ VOID
+ );
+
+//
+// Static data.
+//
+
+ULONG ScsiHostId;
+extern PCHAR FirmwareVersion;
+extern PUCHAR ScreenBanner;
+
+//
+// This indicates whether the environment variables or configuration
+// information was changed while the user was in the setup program.
+// If so, we update the ROM data block.
+//
+// A global static is used to minimize the amount of code, and function
+// prototypes and definitions, that has to change.
+//
+
+BOOLEAN SetupROMPendingModified;
+
+ULONG
+JzGetSelection (
+ IN PCHAR Menu[],
+ IN ULONG NumberOfChoices,
+ IN ULONG DefaultChoice,
+ IN PCHAR MenuTitle,
+ IN PCHAR BottomExtraLine1,
+ IN PCHAR BottomExtraLine2,
+ IN LONG AutobootValue,
+ IN BOOLEAN ShowTheTime
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a menu selection from the user.
+
+Arguments:
+
+ Menu Supplies an array of pointers to menu character
+ strings.
+
+ Selections Supplies the number of menu selections.
+
+ DefaultChoice Supplies the current default choice.
+
+ MenuTitle Points to a string that is the name of this menu.
+
+ BottomExtraLine1, If non-NULL, points to strings that should be
+ BottomExtraLine2 printed out below the "use arrow keys to select" line.
+
+ AutobootValue If zero, do not do an autoboot countdown.
+ If nonzero, do an autoboot countdown with this value.
+
+ ShowTheTime If true, show the time.
+
+Return Value:
+
+ Returns the value selected, -1 if the escape key was pressed.
+
+--*/
+{
+ ULONG Index;
+
+ //
+ // Clear screen and print banner.
+ //
+
+ FwSetScreenColor(ArcColorWhite, ArcColorBlue);
+ FwSetScreenAttributes( TRUE, FALSE, FALSE);
+ FwClearScreen();
+
+ FwSetPosition( 0, 0);
+ FwPrint(FW_ARC_MULTIBOOT_MSG, FirmwareVersion);
+ FwPrint(FW_COPYRIGHT_MSG);
+ FwPrint(SS_SELECTION_MENU_MSG, MenuTitle);
+
+ FwSetPosition(NumberOfChoices + 8, 0);
+ FwPrint(FW_USE_ARROW_AND_ENTER_MSG);
+ if (BottomExtraLine1 != NULL) {
+ FwSetPosition(NumberOfChoices + 9, 0);
+ FwPrint(BottomExtraLine1);
+ }
+ if (BottomExtraLine2 != NULL) {
+ FwSetPosition(NumberOfChoices + 10, 0);
+ FwPrint(BottomExtraLine2);
+ }
+
+ if (AutobootValue != 0) {
+ FwPrint(FW_AUTOBOOT_MSG);
+ }
+
+ //
+ // Display the menu and the wait for an action to be selected.
+ //
+
+ DefaultChoice = JzDisplayMenu(Menu,
+ NumberOfChoices,
+ DefaultChoice,
+ 7,
+ AutobootValue,
+ ShowTheTime);
+
+ //
+ // Clear the choices.
+ //
+
+ for (Index = 0; Index < NumberOfChoices ; Index++ ) {
+ VenSetPosition( Index + 7, 5);
+ VenPrint1("%cK", ASCII_CSI);
+ }
+
+ return(DefaultChoice);
+}
+
+ULONG
+JzInitializeScsiHostId (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets the ScsiHostId from the configuration database if it
+ exists.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The ScsiHostId is read from the ScsiController configuration component
+ if it exists. If not, a value of 7 is returned.
+
+--*/
+{
+ PCONFIGURATION_COMPONENT Component;
+ PCM_SCSI_DEVICE_DATA ScsiDeviceData;
+ UCHAR Buffer[sizeof(CM_PARTIAL_RESOURCE_LIST) +
+ (sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * 5) +
+ sizeof(CM_SCSI_DEVICE_DATA)];
+ PCM_PARTIAL_RESOURCE_LIST Descriptor = (PCM_PARTIAL_RESOURCE_LIST)&Buffer;
+ ULONG Count;
+
+ if (((Component = ArcGetComponent("scsi(0)")) != NULL) &&
+ (Component->Class == AdapterClass) && (Component->Type == ScsiAdapter) &&
+ (ArcGetConfigurationData((PVOID)Descriptor, Component) == ESUCCESS) &&
+ ((Count = Descriptor->Count) < 6)) {
+
+ ScsiDeviceData = (PCM_SCSI_DEVICE_DATA)&Descriptor->PartialDescriptors[Count];
+
+ if (ScsiDeviceData->HostIdentifier > 7) {
+ return(7);
+ } else {
+ return(ScsiDeviceData->HostIdentifier);
+ }
+ }
+
+ return(7);
+
+}
+
+
+VOID
+JensenSetupProgram(
+ OUT PBOOLEAN RunAProgram,
+ OUT PCHAR PathName
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is the top level of the setup utility.
+
+Arguments:
+
+ RunAProgram - A pointer to a boolean that will be set to TRUE
+ if the user wants to run a program.
+
+ PathName - A pointer to a string area for program names.
+ If asked to run a program, this will be loaded with
+ the name of the program to run. For now, this
+ program will be assumed to be run without any
+ arguments.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ BOOLEAN Reboot;
+ BOOLEAN AlreadyFoundAFatalProblem;
+ BOOLEAN DisableChoice[NUMBER_OF_SETUP_MENU_CHOICES];
+ LONG DefaultChoice = 0;
+ ULONG ProblemAreas;
+ ULONG TempX;
+ ULONG Index;
+ ULONG CurrentLine;
+ UCHAR Character;
+ UCHAR YellowString[10];
+ PCHAR AdvisoryString;
+ PCHAR ErrorString = NULL;
+
+ //
+ // The ROM has not been modified yet by the user.
+ //
+
+ SetupROMPendingModified = FALSE;
+
+ //
+ // Initialize the ScsiHostId Value.
+ //
+
+ ScsiHostId = JzInitializeScsiHostId();
+
+ //
+ // Loop on choices until exit is selected.
+ //
+
+ *RunAProgram = FALSE;
+
+ Reboot = FALSE;
+
+ while (TRUE) {
+
+ //
+ // Reset the setup menu by clearing the marker area and resetting the
+ // foreground color at the beginning of each line to white, and reset
+ // the choice-disable array.
+ //
+
+ sprintf(YellowString, "%c3%dm ", ASCII_CSI, ArcColorWhite);
+
+ for (Index = 0; Index < NUMBER_OF_SETUP_MENU_CHOICES; Index++) {
+
+ DisableChoice[Index] = FALSE;
+
+ if (SetupMenuChoices[Index] != NULL) {
+ // Be careful not to copy the \0.
+ strncpy(SetupMenuChoices[Index], YellowString, 6);
+ }
+ }
+
+ AdvisoryString = NULL;
+
+ //
+ // Now the setup menu is in its initial default state. Get the
+ // system problem areas.
+ //
+
+ FwSystemConsistencyCheck(TRUE, &ProblemAreas);
+
+ //
+ // Intializing the ROM data has to be done in a particular order. So,
+ // we now cycle through the problem bits and put a colored arrow
+ // next to each area that needs fixing, and at the same time load
+ // the array that tells us which ones are not allowed yet.
+ //
+ // This code is not general-purpose. It knows about the order of
+ // SetupMenuChoices and the desired order of problem repair.
+ //
+
+ sprintf(YellowString, "%c3%dm->", ASCII_CSI, ArcColorYellow);
+
+ AlreadyFoundAFatalProblem = FALSE;
+ TempX = ProblemAreas;
+ Index = 0;
+
+ while (TempX != 0) {
+
+ //
+ // There is at least one more system problem.
+ //
+
+ if (((TempX & 1) != 0) || ((TempX & 0x10000) != 0)) {
+
+ //
+ // There is a problem in the area that we are now pointing at,
+ // so make this a yellow line.
+ //
+
+ strncpy (SetupMenuChoices[Index], YellowString, 6);
+ AdvisoryString = SS_YELLOW_MEANS_FIX_THIS_MSG;
+
+ //
+ // Since managing the boot selections is a "yellow" error,
+ // they are orthogonal to fixing fatal ("red") problems.
+ //
+
+ if (Index != SETUP_MENU_BOOT_SELECTION_LINE) {
+
+
+ if (AlreadyFoundAFatalProblem == FALSE) {
+
+ //
+ // Remember that we have found the first fatal
+ // problem already.
+ //
+
+ AlreadyFoundAFatalProblem = TRUE;
+
+ } else {
+
+ //
+ // There is a problem in the area we are now pointing
+ // at, and it is not the first problem found, and this
+ // is not a "Manage boot selections" problem. So,
+ // mark this problem as one which is temporarily
+ // disabled until the more serious problem(s) are
+ // fixed.
+ //
+
+ DisableChoice[Index] = TRUE;
+ }
+ }
+ }
+
+ //
+ // Shift the red and yellow halves right one bit.
+ //
+
+ TempX = ((TempX & FWP_MACHINE_PROBLEMS_RED) >> 1) |
+ (((TempX & FWP_MACHINE_PROBLEMS_YELLOW) >> 17) << 16);
+ Index++;
+ }
+
+ //
+ // Now get the users selection. The last selection is offerred only
+ // if a change is pending. The system time is displayed only if there
+ // are no problems with the system time. We do this until the user
+ // makes an allowed selection.
+ //
+
+ do {
+ DefaultChoice = JzGetSelection(SetupMenuChoices,
+ (SetupROMPendingModified ?
+ NUMBER_OF_SETUP_MENU_CHOICES :
+ NUMBER_OF_SETUP_MENU_CHOICES - 1),
+ DefaultChoice,
+ FW_MENU_SETUP_MSG,
+ AdvisoryString,
+ ErrorString,
+ 0,
+ (ProblemAreas & FWP_MACHINE_PROBLEMS_TIME) ? FALSE : TRUE);
+
+
+ if ((DefaultChoice >= 0) &&
+ (DefaultChoice <= (NUMBER_OF_SETUP_MENU_CHOICES - 1)) &&
+ (DisableChoice[DefaultChoice] == TRUE)) {
+
+ ErrorString = SS_CHOOSE_ANOTHER_ITEM_MSG;
+
+ } else {
+
+ ErrorString = NULL;
+ }
+
+ } while (ErrorString != NULL);
+
+ FwClearScreen();
+
+ //
+ // Switch based on the action.
+ //
+
+ switch (DefaultChoice) {
+
+ //
+ // Set system time
+ //
+
+ case 0:
+
+ JzSetTime();
+ break;
+
+
+ //
+ // Set default environment variables
+ //
+
+ case 1:
+
+ JzMakeDefaultEnvironment(FALSE);
+ break;
+
+
+ //
+ // Set default configuration
+ //
+
+ case 2:
+
+ Reboot = JzMakeDefaultConfiguration(FALSE) || Reboot;
+ break;
+
+
+ //
+ // Manage boot selections
+ //
+
+ case 3:
+
+ JzBootMenu();
+ break;
+
+
+ //
+ // Setup autoboot
+ //
+
+ case 4:
+
+ JzSetupAutoboot(FALSE);
+ break;
+
+
+ //
+ // Menu spacer selections
+ //
+
+ case 5:
+ case 9:
+
+ break;
+
+
+ //
+ // Run EISA configuration utility from a floppy. If a
+ // reboot is pending, we reboot after setting the auto-run
+ // NVRAM flag. If a ROM update is pending, do the update first.
+ //
+
+ case 6:
+
+#ifdef ISA_PLATFORM
+
+ break;
+
+#else
+
+ if (SetupROMPendingModified) {
+ JzUpdateROMData();
+ }
+
+ if (Reboot) {
+
+ FwpWriteIOChip(RTC_APORT, RTC_RAM_NT_FLAGS0);
+ Character = FwpReadIOChip(RTC_DPORT);
+ ((PRTC_RAM_NT_FLAGS_0)(&Character))->AutoRunECU = 1;
+ FwpWriteIOChip(RTC_APORT, RTC_RAM_NT_FLAGS0);
+ FwpWriteIOChip(RTC_DPORT, Character);
+
+ FwPrint(SS_ECU_WILL_NOW_REBOOT_MSG);
+ FwStallExecution(3 * 1000 * 1000);
+ ArcReboot();
+ }
+
+ *RunAProgram = TRUE;
+ strcpy(PathName, FW_ECU_LOCATION);
+ return;
+
+#endif
+
+ //
+ // Edit environment variables
+ //
+
+ case 7:
+
+ JzEditVariable();
+ break;
+
+
+ //
+ // Reset to factory defaults
+ //
+
+ case 8:
+
+ FwSetPosition(3, 0);
+ FwPrint(SS_RESET_TO_FACTORY_DEFAULTS_WARNING_MSG);
+ CurrentLine = 7;
+ CurrentLine = JzGetYesNo(&CurrentLine, SS_ARE_YOU_SURE_MSG, TRUE);
+
+ if (CurrentLine == 0) {
+ JzMakeDefaultEnvironment(TRUE);
+ Reboot = JzMakeDefaultConfiguration(TRUE);
+ JzAddBootSelection(TRUE);
+ JzSetupAutoboot(TRUE);
+ }
+
+ break;
+
+ //
+ // Help
+ //
+
+ case 10:
+
+ FwSetPosition(3,0);
+ for (Index = 0; Index < SETUP_HELP_TABLE_SIZE; Index++) {
+ if (SETUP_HELP_TABLE[Index] != NULL) {
+ FwPrint(SETUP_HELP_TABLE[Index]);
+ }
+ FwPrint(SS_CRLF_MSG);
+ }
+
+ FwWaitForKeypress(TRUE);
+ break;
+
+
+ //
+ // Switch to OpenVMS or OSF
+ //
+
+ case 11:
+
+ FwOperatingSystemSwitch();
+ break;
+
+ //
+ // Quit.
+ //
+
+ case 12:
+
+ FwEnvironmentLoad();
+ FwRestoreConfiguration();
+ return;
+
+ //
+ // Exit, and escape key
+ //
+
+ case -1:
+ case 13:
+ default:
+
+ //
+ // If the escape key was pressed, or something bad happened
+ // in the menu subroutine, ask the user for a confirmation.
+ //
+
+ if ((DefaultChoice != 13) && SetupROMPendingModified) {
+
+ FwSetPosition(3, 0);
+ FwPrint(SS_ESCAPE_FROM_SETUP_MSG);
+
+ while (ArcGetReadStatus(ARC_CONSOLE_INPUT) != ESUCCESS) {
+ JzShowTime(FALSE);
+ }
+
+ ArcRead(ARC_CONSOLE_INPUT, &Character, 1, &Index);
+
+ if (Character == ASCII_ESC) {
+ FwEnvironmentLoad();
+ FwRestoreConfiguration();
+ return;
+ }
+ }
+
+ if (SetupROMPendingModified) {
+ JzUpdateROMData();
+ }
+
+ if (Reboot) {
+ ArcReboot();
+ }
+ return;
+
+ }
+ }
+}
+
+
+BOOLEAN
+JzBootMenu(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine displays the boot menu.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns TRUE if something was probably changed, and FALSE if nothing
+ was changed.
+
+--*/
+{
+ BOOLEAN FoundProblems;
+ BOOLEAN PreviousROMPending;
+ LONG DefaultChoice = 0;
+
+ //
+ // Loop on choices until exit is selected.
+ //
+ // Right now, the test for a pending ROM change is to look for a change
+ // in the global SetupROMPendingModified. This test is too pessimistic,
+ // and could be made more discriminating.
+ //
+
+ PreviousROMPending = SetupROMPendingModified;
+ SetupROMPendingModified = FALSE;
+
+ while (TRUE) {
+
+ DefaultChoice = JzGetSelection(ManageBootSelectionChoices,
+ NUMBER_OF_SS_MANAGE_BOOT_CHOICES,
+ DefaultChoice,
+ FW_MENU_BOOT_SELECTIONS_MSG,
+ NULL,
+ NULL,
+ 0,
+ TRUE);
+
+ //
+ // Switch based on the action.
+ //
+
+ switch (DefaultChoice) {
+
+ //
+ // Add boot selection
+ //
+
+ case 0:
+ JzAddBootSelection(FALSE);
+ break;
+
+ //
+ // Change a boot selection
+ //
+
+ case 1:
+ JzEditBootSelection();
+ break;
+
+ //
+ // Check boot selections
+ //
+
+ case 2:
+ JzCheckBootSelections(FALSE, &FoundProblems);
+ break;
+
+ //
+ // Delete a boot selection
+ //
+
+ case 3:
+ JzDeleteBootSelection();
+ break;
+
+ //
+ // Dump boot selections
+ //
+
+ case 4:
+ JzDumpBootSelections();
+ break;
+
+ //
+ // Rearrange boot selections
+ //
+
+ case 5:
+ JzRearrangeBootSelections();
+ break;
+
+ //
+ // Escape Key, or Exit.
+ //
+
+ case -1:
+ default:
+
+ //
+ // Check if a change happened, and restore previous global TRUEness
+ // if necessary.
+ //
+ if (SetupROMPendingModified) {
+ return (TRUE);
+ } else {
+ SetupROMPendingModified = PreviousROMPending;
+ return (FALSE);
+ }
+ }
+ }
+}
+
+VOID
+JzDumpBootSelections(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function gives a crude dump of the current boot selections.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG Count;
+ ULONG IndentAmount;
+ ULONG Index;
+ ULONG Index2;
+ ULONG Number;
+ PCHAR Variable;
+
+ VenClearScreen();
+ VenSetPosition(3, 0);
+
+ for (Number = 0; Number < 6 ; Number++ ) {
+ switch (Number) {
+ case 0:
+ Variable = "LOADIDENTIFIER";
+ IndentAmount = sizeof("LOADIDENTIFIER");
+ break;
+ case 1:
+ Variable = "SYSTEMPARTITION";
+ IndentAmount = sizeof("SYSTEMPARTITION");
+ break;
+ case 2:
+ Variable = "OSLOADER";
+ IndentAmount = sizeof("OSLOADER");
+ break;
+ case 3:
+ Variable = "OSLOADPARTITION";
+ IndentAmount = sizeof("OSLOADPARTITION");
+ break;
+ case 4:
+ Variable = "OSLOADFILENAME";
+ IndentAmount = sizeof("OSLOADFILENAME");
+ break;
+ case 5:
+ Variable = "OSLOADOPTIONS";
+ IndentAmount = sizeof("OSLOADOPTIONS");
+ break;
+ }
+
+ VenPrint1("%s=",Variable);
+ Variable = FwGetVolatileEnvironmentVariable(Variable);
+ if (Variable != NULL) {
+
+ //
+ // If this variable will fit all on one line, print it as such.
+ // Otherwise, print one segment per line.
+ //
+
+ if ((IndentAmount + strlen(Variable)) < DisplayWidth) {
+ VenPrint(Variable);
+ } else {
+ while (strchr(Variable,';') != NULL) {
+ Index = strchr(Variable,';') - Variable + 1;
+ ArcWrite(ARC_CONSOLE_OUTPUT, Variable, Index, &Count);
+ VenPrint(SS_CRLF_MSG);
+ for (Index2 = 0; Index2 < IndentAmount; Index2++) {
+ VenPrint(" ");
+ }
+ Variable += Index;
+ }
+ VenPrint(Variable);
+ }
+ }
+ VenPrint(SS_CRLF_MSG);
+ }
+
+ VenPrint(SS_CRLF_MSG);
+ FwWaitForKeypress(TRUE);
+}
+
+
+VOID
+JzUpdateROMData(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ The user is exiting the setup utility after having changed something
+ in the Configuration or Environment Variables. This function updates
+ the ROM from the volatile areas.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ARC_STATUS Status;
+
+ VenClearScreen();
+ VenSetPosition(0,0);
+ VenPrint(SS_ROM_UPDATE_IN_PROGRESS_MSG);
+ if ((Status = FwSaveConfiguration()) != ESUCCESS) {
+ VenPrint(SS_ROM_UPDATE_FAILED_MSG);
+ ParseARCErrorStatus(Status);
+ }
+
+ return;
+}
+
+VOID
+FwOperatingSystemSwitch(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This lets the user alter the console selection flag in the NVRAM.
+
+Arguments:
+
+ None.
+
+
+Side Effects:
+
+ The RTC_RAM_CONSOLE_SELECTION flag byte in the Jensen NVRAM
+ may be modified.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR Character;
+ ULONG Count;
+ BOOLEAN UserMadeAChange = FALSE;
+ LONG Index;
+ UCHAR PresentChoice;
+
+ while (TRUE) {
+
+ FwClearScreen();
+ FwSetPosition(2, 0);
+ FwPrint(SS_WHICH_OS_QUERY_MSG);
+
+ //
+ // Print out the current boot selection. Although the operating
+ // system selection encodings are hard-wired, the definitions are
+ // also declared in \nt\private\ntos\inc\jnsnrtc.h. The legal
+ // values are 1 -- 3; any other value defaults to booting NT.
+ //
+
+ FwpWriteIOChip(RTC_APORT, RTC_RAM_CONSOLE_SELECTION);
+ PresentChoice = FwpReadIOChip(RTC_DPORT);
+ if ((PresentChoice == 0) || (PresentChoice > 3)) {
+ PresentChoice = RTC_RAM_CONSOLE_SELECTION_NT;
+ }
+
+ FwPrint(SS_BOOT_SELECTION_IS_MSG,
+ OperatingSystemNames[PresentChoice - 1]);
+
+ FwSetPosition((NUMBER_OF_OS_CHOICES + 7), 0);
+ FwPrint(FW_USE_ARROW_AND_ENTER_MSG);
+
+ //
+ // JzDisplayMenu returns -1 or a 0-based menu selection.
+ // The console selection flag is 1-based.
+ //
+
+ Index = JzDisplayMenu(OperatingSystemSwitchChoices,
+ NUMBER_OF_OS_CHOICES,
+ 3,
+ 6,
+ 0,
+ FALSE)
+ + 1;
+
+ if ((Index < 1) || (Index > 3)) {
+
+ //
+ // The user hit escape, selected Return to main menu, or something
+ // bad happened in JzDisplayMenu. Exit this loop.
+ //
+
+ break;
+ }
+
+ //
+ // Change the console selection flag.
+ //
+
+ FwpWriteIOChip(RTC_APORT, RTC_RAM_CONSOLE_SELECTION);
+ FwpWriteIOChip(RTC_DPORT, Index);
+ UserMadeAChange = TRUE;
+ }
+
+
+ //
+ // If the user made a change, tell him to power-cycle.
+ //
+
+ if (UserMadeAChange) {
+ FwSetPosition(2, 0);
+ FwPrint("\x9bK");
+ FwSetPosition(6, 0);
+ FwPrint("%c0J", ASCII_CSI);
+ FwPrint(SS_POWER_CYCLE_FOR_NEW_OS_MSG);
+ FwPrint(SS_PRESS_KEY_MSG);
+ FwRead(ARC_CONSOLE_INPUT, &Character, 1, &Count);
+ }
+}
diff --git a/private/ntos/fw/alpha/jnsettim.c b/private/ntos/fw/alpha/jnsettim.c
new file mode 100644
index 000000000..6320a888f
--- /dev/null
+++ b/private/ntos/fw/alpha/jnsettim.c
@@ -0,0 +1,421 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ jnsettim.c
+
+Abstract:
+
+ This module contains the code to set the time on an Alpha/Jensen.
+
+Author:
+
+ John DeRosa 31-July-1992.
+
+ This module, and the entire setup program, was based on the jzsetup
+ program written by David M. Robinson (davidro) of Microsoft, dated
+ 9-Aug-1991.
+
+Revision History:
+
+--*/
+
+#include "fwp.h"
+#include "jnsnvdeo.h"
+#include "machdef.h"
+
+#ifdef JENSEN
+#include "jnsnrtc.h"
+#else
+#include "mrgnrtc.h" // morgan
+#endif
+
+#include "string.h"
+#include "iodevice.h"
+#include "jnvendor.h"
+#include "fwstring.h"
+
+#if 0
+//
+// JzEisaControlBase is no longer needed.
+// JzRealTimeClockBase never existed on Jensen.
+//
+
+//
+// Static Data
+//
+
+PVOID JzEisaControlBase;
+PVOID JzRealTimeClockBase;
+#endif
+ULONG LastTime = 0;
+
+UCHAR
+JzReadClockRegister (
+ UCHAR Register
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads the specified realtime clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is read.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+{
+ FwpWriteIOChip (RTC_APORT, Register);
+
+ return (FwpReadIOChip(RTC_DPORT));
+}
+
+VOID
+JzWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This routine writes the specified value to the specified realtime
+ clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is written.
+
+ Value - Supplies the value that is written to the specified register.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ FwpWriteIOChip (RTC_APORT, Register);
+
+ FwpWriteIOChip (RTC_DPORT, Value);
+
+ return;
+}
+
+VOID
+JzWriteTime (
+ IN PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the realtime clock.
+
+ N.B. This routine assumes that the caller has provided any required
+ synchronization to set the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that specifies the
+ realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are written to the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+
+ //
+ // If the realtime clock battery is still functioning, then write
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+
+ DataByte = JzReadClockRegister(RTC_CONTROL_REGISTERD);
+ if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) {
+
+ //
+ // Set the realtime clock control to set the time.
+ //
+
+ DataByte = 0;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->HoursFormat = 1;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->DataMode = 1;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 1;
+ JzWriteClockRegister(RTC_CONTROL_REGISTERB, DataByte);
+
+ //
+ // Write the realtime clock values.
+ //
+
+ JzWriteClockRegister(RTC_YEAR, (UCHAR)(TimeFields->Year - 1980));
+ JzWriteClockRegister(RTC_MONTH, (UCHAR)TimeFields->Month);
+ JzWriteClockRegister(RTC_DAY_OF_MONTH, (UCHAR)TimeFields->Day);
+ JzWriteClockRegister(RTC_DAY_OF_WEEK, (UCHAR)(TimeFields->Weekday + 1));
+ JzWriteClockRegister(RTC_HOUR, (UCHAR)TimeFields->Hour);
+ JzWriteClockRegister(RTC_MINUTE, (UCHAR)TimeFields->Minute);
+ JzWriteClockRegister(RTC_SECOND, (UCHAR)TimeFields->Second);
+
+ //
+ // Set the realtime clock control to update the time.
+ //
+
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 0;
+ JzWriteClockRegister(RTC_CONTROL_REGISTERB, DataByte);
+ return;
+
+ } else {
+ return;
+ }
+}
+
+
+BOOLEAN
+JzSetTime (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This sets the system time. It assumes the screen has already been
+ cleared.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns TRUE if the system time was changed.
+
+--*/
+
+{
+
+ UCHAR Character;
+ ULONG Count;
+ PTIME_FIELDS TimeFields;
+ TIME Time;
+ CHAR TimeString[80];
+ CHAR DateString[80];
+ PCHAR StartToken;
+ PCHAR EndToken;
+ GETSTRING_ACTION Action;
+
+#if 0
+ //
+ // Set addresses for RTC access.
+ //
+
+ JzEisaControlBase = (PVOID)EISA_IO_VIRTUAL_BASE;
+ JzRealTimeClockBase = (PVOID)RTC_VIRTUAL_BASE;
+#endif
+
+ VenSetPosition( 3, 5);
+ VenPrint(SS_ENTER_DATE_MSG);
+ do {
+ Action = JzGetString( DateString,
+ sizeof(DateString),
+ NULL,
+ 3,
+ 5 + strlen(SS_ENTER_DATE_MSG),
+ TRUE);
+ if (Action == GetStringEscape) {
+ return (FALSE);
+ }
+ } while ( Action != GetStringSuccess );
+
+ VenSetPosition( 4, 5);
+ VenPrint(SS_ENTER_TIME_MSG);
+ do {
+ Action = JzGetString( TimeString,
+ sizeof(TimeString),
+ NULL,
+ 4,
+ 5 + strlen(SS_ENTER_TIME_MSG),
+ TRUE);
+ if (Action == GetStringEscape) {
+ return (FALSE);
+ }
+ } while ( Action != GetStringSuccess );
+
+ //
+ // Get time
+ //
+
+ TimeFields = ArcGetTime();
+
+ StartToken = DateString;
+ if (*StartToken != 0) {
+ EndToken = strchr(StartToken, '-');
+ if (EndToken != NULL) {
+ *EndToken = 0;
+ TimeFields->Month = atoi(StartToken);
+ StartToken = EndToken + 1;
+ }
+
+ EndToken = strchr(StartToken, '-');
+ if (EndToken != NULL) {
+ *EndToken = 0;
+ TimeFields->Day = atoi(StartToken);
+ StartToken = EndToken + 1;
+ TimeFields->Year = atoi(StartToken);
+ if (TimeFields->Year < 100) {
+ if (TimeFields->Year < 80) {
+ TimeFields->Year += 2000;
+ } else {
+ TimeFields->Year += 1900;
+ }
+ }
+ }
+ }
+
+ StartToken = TimeString;
+ if (*StartToken != 0) {
+ EndToken = strchr(StartToken, ':');
+
+ if (EndToken != NULL) {
+ *EndToken = 0;
+ TimeFields->Hour = atoi(StartToken);
+ StartToken = EndToken + 1;
+ }
+
+ EndToken = strchr(StartToken, ':');
+ if (EndToken != NULL) {
+ *EndToken = 0;
+ TimeFields->Minute = atoi(StartToken);
+ StartToken = EndToken + 1;
+ TimeFields->Second = atoi(StartToken);
+ } else {
+ TimeFields->Minute = atoi(StartToken);
+ TimeFields->Second = 0;
+ }
+
+ }
+
+ if (!RtlTimeFieldsToTime(TimeFields, &Time)) {
+ VenSetPosition( 6, 5);
+ VenPrint(SS_ILLEGAL_TIME_MSG);
+ VenPrint(SS_PRESS_KEY2_MSG);
+ ArcRead(ARC_CONSOLE_INPUT, &Character, 1, &Count);
+ return (FALSE);
+ } else {
+ RtlTimeToTimeFields( &Time, TimeFields);
+ JzWriteTime(TimeFields);
+ return (TRUE);
+ }
+
+}
+
+VOID
+JzShowTime (
+ BOOLEAN First
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+ First - If TRUE then don't check LastTime.
+
+Return Value:
+
+--*/
+
+{
+
+ PTIME_FIELDS TimeFields;
+ TIME Time;
+ BOOLEAN Pm;
+ ULONG ThisTime;
+
+#if 0
+ //
+ // Set addresses for RTC access.
+ //
+
+ JzEisaControlBase = (PVOID)EISA_IO_VIRTUAL_BASE;
+ JzRealTimeClockBase = (PVOID)RTC_VIRTUAL_BASE;
+#endif
+
+ //
+ // See if the time has changed since last time we were called. This is
+ // for when the display is over the serial port, so we do not blast
+ // characters out all the time.
+ //
+
+ ThisTime = ArcGetRelativeTime();
+ if (!First && (ThisTime == LastTime)) {
+ return;
+ }
+ LastTime = ThisTime;
+
+ //
+ // Get and display time, and screen illegal Weekday values.
+ //
+
+ TimeFields = ArcGetTime();
+
+ VenSetPosition( 0, 44);
+ if ((TimeFields->Weekday < 0) || (TimeFields->Weekday > 6)) {
+ VenPrint(Weekday[0]);
+ } else {
+ VenPrint1("%s, ", Weekday[TimeFields->Weekday]);
+ }
+ VenPrint1("%d-", TimeFields->Month);
+ VenPrint1("%d-", TimeFields->Day);
+ VenPrint1("%d ", TimeFields->Year);
+
+ if (TimeFields->Hour >= 12) {
+ Pm = TRUE;
+ } else {
+ Pm = FALSE;
+ }
+
+ if (TimeFields->Hour > 12) {
+ TimeFields->Hour -= 12;
+ } else if (TimeFields->Hour == 0) {
+ TimeFields->Hour = 12;
+ }
+
+ VenPrint1("%d:", TimeFields->Hour);
+ VenPrint1("%02d:", TimeFields->Minute);
+ VenPrint1("%02d ", TimeFields->Second);
+ if (Pm) {
+ VenPrint(SS_PM);
+ } else {
+ VenPrint(SS_AM);
+ }
+
+ //
+ // Clear anything to the end of the line.
+ //
+
+ VenPrint1("%cK", ASCII_CSI);
+
+ return;
+
+}
diff --git a/private/ntos/fw/alpha/jnsnprom.h b/private/ntos/fw/alpha/jnsnprom.h
new file mode 100644
index 000000000..39138eef6
--- /dev/null
+++ b/private/ntos/fw/alpha/jnsnprom.h
@@ -0,0 +1,222 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ jnsnprom.h
+
+Abstract:
+
+ This module is the header file that describes physical and virtual
+ address used by the PROM monitor and boot code in the Alpha PCs.
+ Started from \nt\private\ntos\inc\jazzprom.h.
+
+
+Author:
+
+ David N. Cutler (davec) 27-Apr-1991
+
+
+Revision History:
+
+ 10-May-1992 John DeRosa [DEC]
+
+ Made changes for Alpha/Jensen. With the changes to the Alpha/Jensen
+ meta-virtual linear addresses, this file now defines a different
+ subset of things than the jazzprom.h file did. Note that the
+ ntos\inc\jnsndef.h file defines a few virtual bases, and those
+ bases are not defined here. Why don't we define the virtual bases
+ all in one place? Don't ask.
+
+ 31-March-1993 Bruce Butts [DEC]
+
+ Converted file to QVA macros instead of handcoded QVAs.
+
+--*/
+
+#ifndef _JNSNPROM_
+#define _JNSNPROM_
+
+//
+// N.B. Explicitly include the appropriate machdef file,
+// for builds in other parts of the tree that include fwp.h.
+//
+
+//
+// For EisaIOQVA and EisaMemQVA definitions.
+//
+
+#ifdef JENSEN
+#include "\nt\private\ntos\fw\alpha\jensen\alpha\machdef.h"
+#endif
+
+#ifdef MORGAN
+#include "\nt\private\ntos\fw\alpha\morgan\alpha\machdef.h"
+#endif
+
+
+//
+// The Alpha PC firmware I/O space routines (READ_PORT_UCHAR, etc.)
+// map a quasi-virtual linear address space into EV4 kernel superpages, so that
+// physical = virtual. And, all of the firmware runs in superpage mode as well.
+//
+// The _PHYSICAL_ addresses in \nt\private\ntos\inc\jnsndef.h and mrgndef.h
+// are real physical addresses. Since the Alpha/Jensen firmware source code
+// deals with the quasi-virtual addresses (QVAs), the base symbols that it is
+// compiled with are *not* the real physical addresses, but instead the QVA
+// addresses.
+//
+// The virtual/physical pairs are not strictly necessary for Alpha PCs
+// since memory mapping is off. But, since I need QVA addresses for my
+// I/O anyway, the _VIRTUAL_ duals are in fact QVA addresses, and this is what
+// will be used everywhere in the firmware pointer definitions.
+//
+//
+
+
+//
+// Define symbols for `standard PC' ISA port addresses.
+//
+
+#define FLOPPY_ISA_PORT_ADDRESS 0x3f0
+#define KEYBOARD_ISA_PORT_ADDRESS 0x060
+#define MOUSE_ISA_PORT_ADDRESS 0x060
+#define PARALLEL_ISA_PORT_ADDRESS 0x3bc
+#define SP0_ISA_PORT_ADDRESS 0x3f8
+#define SP1_ISA_PORT_ADDRESS 0x2f8
+
+
+//
+// Define the QVA virtual duals of the real physical base addresses
+// for boot mapping.
+//
+
+//
+// virtual base of EISA I/O
+//
+
+#define EISA_IO_VIRTUAL_BASE EISA_IO_BASE_QVA
+#define DEVICE_VIRTUAL_BASE EISA_IO_BASE_QVA
+
+//
+// On MIPS, this is different from EISA_IO_VIRTUAL_BASE because of the
+// way Microsoft simulated having a system board EISA ID. This is unnecessary for
+// Alpha PCs, and defining this minimizes code changes.
+//
+
+#define EISA_EXTERNAL_IO_VIRTUAL_BASE EISA_IO_VIRTUAL_BASE
+
+//
+// Define magic address for operation control words in the 82357 interrupt
+// controller. This is used only for checking for floppy interrupts.
+//
+
+#define EISA_INT_OCW3 ( EISA_IO_VIRTUAL_BASE | 0x20 )
+
+// virtual base of EISA memory
+
+
+#define EISA_MEMORY_VIRTUAL_BASE EISA_MEM_BASE_QVA
+
+#undef INTERRUPT_VIRTUAL_BASE
+
+//
+// Jensen PROM0 cA base address is 1.8000.0000 hex.
+// PROM1 1.A000.0000 hex.
+//
+// Both PROMs are defined, but the 1MB part is the default PROM.
+//
+//
+
+#define PROM0_VIRTUAL_BASE 0xA0c00000 // virtual base of boot PROM0
+#define PROM1_VIRTUAL_BASE 0xA0d00000 // virtual base of boot PROM1
+#undef PROM_VIRTUAL_BASE
+
+#define PROM_VIRTUAL_BASE PROM1_VIRTUAL_BASE
+
+#define HAE_VIRTUAL_BASE 0xA0E80000 // virtual base of HAE register
+#define SYSCTL_VIRTUAL_BASE 0xA0F00000 // virtual base of SYSCTL register
+
+
+//
+// Jensen has two serial ports. Point "SP_x" at serial port 0.
+//
+
+#undef SP_VIRTUAL_BASE
+
+#define SP0_VIRTUAL_BASE 0xa0e003F8 // virtual base of serial port 0
+ // ISA port = 3F8h
+
+#define SP1_VIRTUAL_BASE 0xa0e002F8 // virtual base of serial port 1
+ // ISA port = 2F8h
+
+#define SP_VIRTUAL_BASE SP0_VIRTUAL_BASE // virtual base, serial port
+
+#define RTC_VIRTUAL_BASE 0xa0e00170 // virtual base, realtime clock
+ // ISA port = 170h
+
+#define KEYBOARD_VIRTUAL_BASE 0xa0e00060 // virtual base, keyboard control
+ // ISA port = 060h
+
+
+//
+// I will maintain the comport / serial port # skew that was present in
+// the Jazz code. /jdr
+//
+
+// virtual base of comport 1 control
+#define COMPORT1_VIRTUAL_BASE SP0_VIRTUAL_BASE
+
+// virtual base of comport 2 control
+#define COMPORT2_VIRTUAL_BASE SP1_VIRTUAL_BASE
+
+
+#define PARALLEL_VIRTUAL_BASE 0xa0e003BC // virtual base of parallel port.
+ // ISA port = 3BCh
+
+//
+// Define register offsets for the Combo chip's RTC.
+//
+// These are used with the WriteVti and ReadVti functions.
+//
+
+#define RTC_REGNUMBER_RTC_CR1 0x6A
+
+//
+// Define virtual base address for `standard PC' floppy controller, i.e. an
+// ISA Intel 82077A. Note: A corresponding _PHYSICAL_BASE definition is not
+// defined anywhere.
+//
+
+#define FLOPPY_VIRTUAL_BASE EisaIOQva(0x03F0) // This is ISA space
+ // @ 3F0H
+
+#undef INTERRUPT_SOURCE
+
+
+//
+// Define magic value to ask the interrupt controller to return
+// the IRR interrupt wires through OCW3.
+//
+#define EISA_INT_OCW3_IRR 0xa
+
+
+//
+// Define device interrupt identification values.
+//
+
+#define PARALLEL_DEVICE 0x04 // Parallel port device interrupt id
+#define FLOPPY_DEVICE 0x08 // Floppy device interrupt id
+#define SOUND_DEVICE 0x0C // Sound device interrupt id
+#define VIDEO_DEVICE 0x10 // Video device interrupt id
+#define ETHERNET_DEVICE 0x14 // Ethernet device interrupt id
+#define SCSI_DEVICE 0x18 // SCSI device interrupt id
+#define KEYBOARD_DEVICE 0x1C // Keyboard device interrupt id
+#define MOUSE_DEVICE 0x20 // Mouse device interrupt id
+#define SERIAL0_DEVICE 0x24 // Serial port 0 device interrupt id
+#define SERIAL1_DEVICE 0x28 // Serial port 1 device interrupt id
+
+
+#endif // _JNSNPROM_
diff --git a/private/ntos/fw/alpha/jnsnvdeo.h b/private/ntos/fw/alpha/jnsnvdeo.h
new file mode 100644
index 000000000..50a9a8cc7
--- /dev/null
+++ b/private/ntos/fw/alpha/jnsnvdeo.h
@@ -0,0 +1,206 @@
+/*++
+
+Copyright (c) 1991-1992 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ jnsnvdeo.h
+
+Abstract:
+
+ This header file defines values for standard VGA alphanumeric color mode
+ video. (Graphics and BW mode are not defined.)
+
+ Addresses are based on the VGA video ISA base address.
+
+ This was started from \nt\private\ntos\inc\jazzvdeo.h, and included
+ fw\alpha\vga.h.
+
+
+Author:
+
+ John Cooper (johncoop) 25-Jul-1991
+ David N. Cutler (davec) 27-Apr-1991
+
+
+Revision History:
+
+ 21-August-1992 John DeRosa [DEC]
+
+ Added Alpha modifications. For now this just describes
+ enough of the VGA architecture for firmware use.
+
+
+ Andre Vachon (andreva) 09-Mar-1992
+
+ Combined the G300 and G364 definitions files into one so that we only
+ need one driver for the Jazz system.
+
+--*/
+
+//
+// Define video controller parameters.
+//
+
+//
+// Define VGA registers. This starts at ISA space 0x3C0.
+//
+
+typedef struct _VGA_READ_REGISTERS {
+ UCHAR reserved0;
+ UCHAR attribute_adddata; // 3c1
+ UCHAR input_status_0; // 3c2
+ UCHAR reserved1;
+ UCHAR sequencer_address; // 3c4
+ UCHAR sequencer_data; // 3c5
+ UCHAR pel_mask; // 3c6
+ UCHAR dac_state; // 3c7
+ UCHAR pel_address_write_mode; // 3c8
+ UCHAR pel_data; // 3c9
+ UCHAR feature_control; // 3ca
+ UCHAR reserved2;
+ UCHAR misc_output; // 3cc
+ UCHAR reserved3;
+ UCHAR graphics_address; // 3ce
+ UCHAR graphics_data; // 3cf
+ UCHAR reserved4[4];
+ UCHAR crtc_address; // 3d4
+ UCHAR crtc_data; // 3d5
+ UCHAR reserved5[4];
+ UCHAR input_status_1; // 3da
+} VGA_READ_REGISTERS, *PVGA_READ_REGISTERS;
+
+
+typedef struct _VGA_WRITE_REGISTERS {
+ UCHAR attribute_adddata; // 3c0
+ UCHAR reserved0;
+ UCHAR misc_output; // 3c2
+ UCHAR reserved1;
+ UCHAR sequencer_address; // 3c4
+ UCHAR sequencer_data; // 3c5
+ UCHAR pel_mask; // 3c6
+ UCHAR pel_address_read_mode; // 3c7
+ UCHAR pel_address_write_mode; // 3c8
+ UCHAR pel_data; // 3c9
+ UCHAR reserved2[4];
+ UCHAR graphics_address; // 3ce
+ UCHAR graphics_data; // 3cf
+ UCHAR reserved3[4];
+ UCHAR crtc_address; // 3d4
+ UCHAR crtc_data; // 3d5
+ UCHAR reserved[4];
+ UCHAR feature_control; // 3da
+} VGA_WRITE_REGISTERS, *PVGA_WRITE_REGISTERS;
+
+
+
+
+//
+// Define indices
+//
+
+// Sequencer register indices
+#define VGA_RESET 0
+#define VGA_CLOCKING_MODE 1
+#define VGA_MAP_MASK 2
+#define VGA_CHAR_MAP_SELECT 3
+#define VGA_MEMORY_MODE 4
+
+// CRT controller register indices
+#define VGA_HORIZONTAL_TOTAL 0
+#define VGA_HORIZONTAL_DISPLAY_END 1
+#define VGA_START_HORIZONTAL_BLANKING 2
+#define VGA_END_HORIZONTAL_BLANKING 3
+#define VGA_START_HORIZONTAL_RETRACE 4
+#define VGA_END_HORIZONTAL_RETRACE 5
+#define VGA_VERTICAL_TOTAL 6
+#define VGA_OVERFLOW 7
+#define VGA_PRESET_ROW_SCAN 8
+#define VGA_MAXIMUM_SCAN_LINE 9
+#define VGA_CURSOR_START 0xa
+#define VGA_CURSOR_END 0xb
+#define VGA_START_ADDRESS_HIGH 0xc
+#define VGA_START_ADDRESS_LOW 0xd
+#define VGA_CURSOR_LOCATION_HIGH 0xe
+#define VGA_CURSOR_LOCATION_LOW 0xf
+#define VGA_VERTICAL_RETRACE_START 0x10
+#define VGA_VERTICAL_RETRACE_END 0x11
+#define VGA_VERTICAL_DISPLAY_END 0x12
+#define VGA_OFFSET 0x13
+#define VGA_UNDERLINE_LOCATION 0x14
+#define VGA_START_VERTICAL_BLANK 0x15
+#define VGA_END_VERTICAL_BLANK 0x16
+#define VGA_MODE_CONTROL 0x17
+#define VGA_LINE_COMPARE 0x18
+// Non-standard VGA defines for the S3 911, 924, 928 chips
+#define VGA_S3924_S3R0 0x30
+#define VGA_S3924_S3R1 0x31
+#define VGA_S3924_S3R2 0x32
+#define VGA_S3924_S3R3 0x33
+#define VGA_S3924_S3R4 0x34
+#define VGA_S3924_S3R5 0x35
+#define VGA_S3924_S3R8 0x38
+#define VGA_S3924_S3R9 0x39
+#define VGA_S3924_S3RA 0x3A
+#define VGA_S3924_S3RB 0x3B
+#define VGA_S3924_SC0 0x40
+#define VGA_S3924_SC2 0x42
+#define VGA_S3924_SC3 0x43
+#define VGA_S3924_SC5 0x45
+
+// Graphics controller register indices
+#define VGA_SET_RESET 0
+#define VGA_ENABLE_SET_RESET 1
+#define VGA_COLOR_COMPARE 2
+#define VGA_DATA_ROTATE 3
+#define VGA_READ_MAP_SELECT 4
+#define VGA_MODE 5
+#define VGA_MISCELLANEOUS 6
+#define VGA_COLOR_DONT_CARE 7
+#define VGA_BIT_MASK 8
+
+// Attribute controller register indices
+#define VGA_PALETTE0 0
+#define VGA_PALETTE1 1
+#define VGA_PALETTE2 2
+#define VGA_PALETTE3 3
+#define VGA_PALETTE4 4
+#define VGA_PALETTE5 5
+#define VGA_PALETTE6 6
+#define VGA_PALETTE7 7
+#define VGA_PALETTE8 8
+#define VGA_PALETTE9 9
+#define VGA_PALETTEA 0xa
+#define VGA_PALETTEB 0xb
+#define VGA_PALETTEC 0xc
+#define VGA_PALETTED 0xd
+#define VGA_PALETTEE 0xe
+#define VGA_PALETTEF 0xf
+#define VGA_ATTR_MODE_CONTROL 0x10
+#define VGA_OVERSCAN 0x11
+#define VGA_COLOR_PLANE_ENABLE 0x12
+#define VGA_HORIZONTAL_PIXEL_PANNING 0x13
+#define VGA_COLOR_SELECT 0x14
+#define VGA_SET_PAS 0x20
+
+//
+// Define G300 configuration data structure.
+// To minimize code changes, Alpha/Jensen will use the same structure.
+//
+
+typedef struct _JAZZ_G300_CONFIGURATION_DATA {
+ USHORT Version;
+ USHORT Revision;
+ USHORT Irql;
+ USHORT Vector;
+ ULONG ControlBase;
+ ULONG ControlSize;
+ ULONG CursorBase;
+ ULONG CursorSize;
+ ULONG FrameBase;
+ ULONG FrameSize;
+} JAZZ_G300_CONFIGURATION_DATA, *PJAZZ_G300_CONFIGURATION_DATA;
+
+typedef JAZZ_G300_CONFIGURATION_DATA JENSEN_CONFIGURATION_DATA;
+typedef PJAZZ_G300_CONFIGURATION_DATA PJENSEN_CONFIGURATION_DATA;
diff --git a/private/ntos/fw/alpha/jnupass.s b/private/ntos/fw/alpha/jnupass.s
new file mode 100644
index 000000000..c40691e06
--- /dev/null
+++ b/private/ntos/fw/alpha/jnupass.s
@@ -0,0 +1,181 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+
+Module Name:
+
+ jnupass.s
+
+
+Abstract:
+
+ This contains assembler code routines for the Alpha
+ firmware update programs (e.g., JNUPDATE.EXE).
+
+
+Author:
+
+ John DeRosa [DEC] 21-May-1992
+
+
+Environment:
+
+ Executes in kernel mode.
+
+Revision History:
+
+ Bruce Butts [DEC] 04-June-1993
+
+ Added functions to read and write Morgan control space registers.
+
+
+--*/
+
+#include "ksalpha.h"
+#include "machdef.h"
+
+/*****************************************************************
+
+Simple functions to perform memory barriers. These are needed because
+our current compiler does not do asm's.
+
+******************************************************************/
+
+
+ LEAF_ENTRY(AlphaInstIMB)
+
+ callpal imb
+ ret zero, (ra)
+
+ .end AlphaInstIMB
+
+
+
+ LEAF_ENTRY(AlphaInstMB)
+
+ mb
+ ret zero, (ra)
+
+ .end AlphaInstMB
+
+
+
+ LEAF_ENTRY(AlphaInstHalt)
+
+ callpal halt
+ ret zero, (ra) # should never return, but...
+
+ .end AlphaInstHalt
+
+
+#ifdef MORGAN
+
+/*****************************************************************
+
+Functions to read and write Morgan Harley chip set control
+registers. This routines are very similar to the HAL functions
+READ_REGISTER_ULONG and WRITE_REGISTER_ULONG; the difference is
+that bits <4:0> of the physical address of the control register
+*must be zero*, instead of a 0x18 as in the HAL functions.
+Addresses supplied are normal QVA of the desired control register.
+
+******************************************************************/
+
+
+ LEAF_ENTRY(READ_CONTROL_REGISTER_ULONG)
+
+/*++
+
+Routine Description:
+
+ Reads a longword location from Morgan control register space.
+
+
+Arguments:
+
+ a0 QVA of longword to be read.
+
+
+Return Value:
+
+ v0 Register data.
+
+--*/
+
+ and a0, QVA_SELECTORS, t1 # get qva selector bits
+ xor t1, QVA_ENABLE, t1 # ok iff QVA_ENABLE set in selectors
+ bne t1, 2f # if ne, iff failed
+
+ zap a0, 0xf0, a0 # clear <63:32>
+ bic a0, QVA_ENABLE,a0 # clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0
+ ldiq t4, -0x4000
+ sll t4, 28, t4
+ or t0, t4, t0 # superpage mode
+
+// or t0, IO_LONG_LEN, t0 # or in the byte enables
+
+ ldl v0, (t0) # read the longword
+ ret zero, (ra)
+
+2:
+//
+// On non-I/O space access, do a normal memory operation
+//
+ ldl v0, (a0) # read the longword
+ ret zero, (ra)
+
+
+ .end READ_CONTROL_REGISTER_ULONG
+
+
+
+ LEAF_ENTRY(WRITE_CONTROL_REGISTER_ULONG)
+
+/*++
+
+Routine Description:
+
+ Writes a longword location to I/O space.
+
+
+Arguments:
+
+ a0 QVA of longword to be read.
+ a1 Longword to be written.
+
+
+Return Value:
+
+ None.
+
+
+--*/
+
+ and a0, QVA_SELECTORS, t1 # get qva selector bits
+ xor t1, QVA_ENABLE, t1 # ok iff QVA_ENABLE set in selectors
+ bne t1, 2f # if ne, iff failed
+
+ zap a0, 0xf0, a0 # clear <63:32>
+ bic a0, QVA_ENABLE,a0 # clear QVA fields so shift is correct
+ sll a0, IO_BIT_SHIFT, t0
+ ldiq t4, -0x4000
+ sll t4, 28, t4
+ or t0, t4, t0 # superpage mode
+
+// or t0, IO_LONG_LEN, t0 # or in the byte enables
+
+ stl a1, (t0) # write the longword
+ mb # order the write
+ ret zero, (ra)
+
+2:
+// BREAK_DEBUG_STOP # _KDA_ don't want this access
+ stl a1, (a0) # store the longword
+ ret zero, (ra)
+
+ .end WRITE_CONTROL_REGISTER_ULONG
+
+
+#endif // ifdef MORGAN
diff --git a/private/ntos/fw/alpha/jnupdate.c b/private/ntos/fw/alpha/jnupdate.c
new file mode 100644
index 000000000..4eafe98e9
--- /dev/null
+++ b/private/ntos/fw/alpha/jnupdate.c
@@ -0,0 +1,1450 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ jnupdate.c
+
+Abstract:
+
+ The main module for the JNUPDATE.EXE Jensen firwmare update program.
+
+Author:
+
+ John DeRosa 14-October-1992
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+
+--*/
+
+#include "fwp.h"
+#include "machdef.h"
+//#include "jnsnrtc.h"
+#include "string.h"
+#include "jnfs.h"
+#include "jnvendor.h"
+#include "iodevice.h"
+#include "rom.h"
+#include "fwupstr.h"
+
+
+// Number of times we will try to update a block before telling the user.
+#define ROM_BLOCK_RETRY_COUNT 4
+
+
+#define MAXIMUM_IDENTIFIER_LENGTH 400
+
+#define MAXIMUM_NUMBER_ROM_BLOCKS 16
+
+#define MINIMUM_UPDATE_FILE_SIZE ( 5 + \
+ (SIXTY_FOUR_KB * 1) + \
+ 4 )
+#define MAXIMUM_UPDATE_FILE_SIZE ( MAXIMUM_IDENTIFIER_LENGTH + \
+ (SIXTY_FOUR_KB * 16 ) + \
+ 4 )
+
+//
+// The type of ROM in this machine, and the array that that describes
+// how to talk to different kinds of ROMs.
+//
+
+extern ROM_TYPE MachineROMType;
+extern ROM_VALUES RomValues[InvalidROM];
+
+//
+// The indicator of a bad Firmware stack for _RtlCheckStack
+//
+ULONG FwRtlStackPanic;
+
+extern PCHAR FirmwareVersion;
+
+//
+// Function prototypes
+//
+
+ARC_STATUS
+FwpFindCDROM (
+ OUT PCHAR PathName
+ );
+
+#ifdef MORGAN
+
+VOID
+MorganReadFlashRomId(
+ ULONG MorganFlashRomChipSelect,
+ PULONG MfgCode,
+ PULONG DeviceCode
+ );
+
+ULONG
+MorganBlastFlash(
+ ULONG MorganFlashRomChipSelect,
+ PUCHAR FirmwareStart,
+ ULONG FirmwareBufferLength
+ );
+
+ARC_STATUS
+MorganFsStoreIntoROM(
+ IN ULONG MorganFlashRomChipSelect,
+ IN PUCHAR FirmwareStart,
+ IN ULONG FirmwareBufferLength
+ );
+
+
+#endif // ifdef MORGAN
+
+
+VOID
+main (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This calls other functions to communicate with the user, get the
+ firmware update file, verify it, and do the update.
+
+ Success and error messages are printed out by this function
+ and/or functions below this one.
+
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ARC_STATUS Status;
+ LONG Index;
+ ULONG CurrentLine;
+ ULONG FirmwareBufferAddress;
+ ULONG FirmwareBufferLength;
+ ULONG FirmwareStart;
+ ULONG HighROMBlockToBeWritten;
+ ULONG LowROMBlockToBeWritten;
+ BOOLEAN VariableFound;
+ PCONFIGURATION_COMPONENT Controller;
+ PCHAR Colon;
+ PCHAR EnvironmentValue;
+ CHAR PathName[128];
+ PCHAR TempArgs;
+ CHAR UserSpecifiedPath[128];
+ GETSTRING_ACTION Action;
+ PCONFIGURATION_COMPONENT Cdrom;
+
+
+ FwRtlStackPanic = 0;
+
+ VenClearScreen();
+
+ VenSetPosition(1,0);
+
+ VenPrint1(FWUP_INTRO1_MSG, FirmwareVersion);
+ VenPrint (FWUP_INTRO2_MSG);
+ VenPrint (FWUP_INTRO3_MSG);
+
+ if (!JnFsProceedWithUpdate()) {
+ return;
+ }
+
+ VenClearScreen();
+
+ VenSetPosition(1,0);
+ VenPrint(FWUP_SELECT_LOCATION_MSG);
+ VenPrint(FWUP_USE_ARROW_KEYS_MSG);
+ VenPrint(FWUP_HIT_ESC_TO_ABORT_MSG);
+
+ Index = JzDisplayMenu(UpdateLocationChoices,
+ NUMBER_OF_UPDATELOCATIONCHOICES,
+ 0,
+ 7,
+ 0,
+ FALSE);
+
+ CurrentLine = 12;
+
+ switch (Index) {
+
+ //
+ // Floppy drive
+ //
+ case 0:
+
+ strcpy(PathName, FWUP_DEFAULT_FLOPPY_LOCATION);
+ break;
+
+ //
+ // CD-ROM
+ //
+ case 1:
+
+ FwpFindCDROM(PathName);
+ strcat(PathName, FWUP_DEFAULT_CDROM_FILENAME);
+ break;
+
+ //
+ // Some other location
+ //
+ case 2:
+
+ VenSetPosition(12,0);
+ VenPrint(FWUP_LOCATION_OF_UPDATE_FILE_MSG);
+ do {
+ Action = JzGetString(UserSpecifiedPath,
+ sizeof(UserSpecifiedPath),
+ NULL,
+ 12,
+ strlen(FWUP_LOCATION_OF_UPDATE_FILE_MSG),
+ FALSE
+ );
+
+ } while ((Action != GetStringEscape) && (Action != GetStringSuccess));
+
+ if (Action == GetStringEscape) {
+ return;
+ }
+
+ CurrentLine += 2;
+
+
+ //
+ // Strip off any arguments.
+ //
+
+ if ((TempArgs = strchr(UserSpecifiedPath, ' ')) != NULL) {
+ *TempArgs++ = 0;
+ }
+
+ //
+ // If the name does not contain a "(", then assume it is not a full
+ // pathname.
+ //
+
+ if (strchr( UserSpecifiedPath, '(') == NULL) {
+
+ //
+ // If the name contains a semicolon, look for an environment
+ // variable that defines the path.
+ //
+
+ if ((Colon = strchr( UserSpecifiedPath, ':')) != NULL) {
+
+ for (Index = 0; UserSpecifiedPath[Index] != ':' ; Index++ ) {
+ PathName[Index] = tolower(UserSpecifiedPath[Index]);
+ }
+
+ PathName[Index++] = ':';
+ PathName[Index++] = 0;
+ EnvironmentValue = ArcGetEnvironmentVariable(PathName);
+ VariableFound = FALSE;
+
+ if (EnvironmentValue != NULL) {
+ strcpy( PathName, EnvironmentValue);
+ VariableFound = TRUE;
+ } else if (!strcmp(PathName, "cd:")) {
+ for ( Index = 0 ; Index < 8 ; Index++ ) {
+ sprintf(PathName, "scsi(0)cdrom(%d)fdisk(0)", Index);
+ Controller = ArcGetComponent(PathName);
+ if ((Controller != NULL) && (Controller->Type == FloppyDiskPeripheral)) {
+ VariableFound = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (!VariableFound) {
+ VenSetPosition( 17, 0);
+ VenSetScreenColor(ArcColorRed, ArcColorWhite);
+ VenPrint(FWUP_UNDEFINED_PATHNAME_MSG);
+ FwWaitForKeypress(FALSE);
+ VenSetScreenColor(ArcColorWhite, ArcColorBlue);
+ return;
+ } else {
+ strcat( PathName, Colon + 1);
+ }
+
+ } else {
+
+ //
+ // The filespec does not contain a '(' or a :.
+ // FWSEARCHPATH is not supported in this tool.
+ // Therefore, declare an error.
+ //
+
+ VenSetPosition( 17, 0);
+ VenSetScreenColor(ArcColorRed, ArcColorWhite);
+ VenPrint1(FWUP_BAD_PATHNAME_MSG, UserSpecifiedPath);
+ FwWaitForKeypress(FALSE);
+ VenSetScreenColor(ArcColorWhite, ArcColorBlue);
+ return;
+ }
+
+ } else {
+ strcpy( PathName, UserSpecifiedPath);
+ }
+ break;
+
+
+ //
+ // Exit, or internal error.
+ //
+ case 3:
+ default:
+ return;
+
+ }
+
+ VenSetPosition(CurrentLine, 0);
+ VenPrint(FWUP_LOCATING_THE_FILE_MSG);
+
+ Status = ReadAndVerifyUpdateFile(PathName, &FirmwareBufferAddress,
+ &FirmwareStart,
+ &FirmwareBufferLength,
+ &LowROMBlockToBeWritten,
+ &HighROMBlockToBeWritten);
+
+ if (Status != ESUCCESS) {
+ JnFsDecodeBadStatus(Status);
+ FwWaitForKeypress(FALSE);
+ return;
+ }
+
+ VenClearScreen();
+
+ VenSetPosition(1,0);
+ VenPrint(FWUP_UPDATE_FILE_IS_GOOD_MSG);
+
+ VenPrint ((PUCHAR)FirmwareBufferAddress);
+
+ //
+ // If manufacturing followed the rules, we should be at or above row #14.
+ //
+
+ VenPrint("\r\n\n");
+ if (!JnFsProceedWithUpdate()) {
+ return;
+ }
+
+ VenPrint(FWUP_ARE_YOU_REALLY_SURE_MSG);
+
+ if (!JnFsProceedWithUpdate()) {
+ return;
+ }
+
+#ifdef JENSEN
+ Status = JnFsStoreIntoROM((PUCHAR)FirmwareStart, LowROMBlockToBeWritten,
+ HighROMBlockToBeWritten);
+#endif // JENSEN
+
+#ifdef MORGAN
+ VenPrint1(FWUP_ABOUT_TO_WRITE_ROM_MSG, LowROMBlockToBeWritten);
+ FwWaitForKeypress();
+ Status = MorganFsStoreIntoROM( LowROMBlockToBeWritten, (PUCHAR)FirmwareStart,
+ FirmwareBufferLength);
+#endif // MORGAN
+
+ if (Status != ESUCCESS) {
+ JnFsDecodeBadStatus(Status);
+ VenPrint(FWUP_FAILED_UPDATE_MSG);
+ } else {
+ VenPrint(FWUP_SUCCESSFUL_UPDATE_MSG);
+ }
+
+ FwWaitForKeypress(FALSE);
+ return;
+
+}
+
+BOOLEAN
+HackGetYesNo (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This asks the user to type a Y or N for a debug clause located later
+ in this module. This is only needed while I am trying to understand the
+ FlashFile ROM update failures, and should be removed when the
+ problem is resolved.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ TRUE if the user hits the Y key.
+ FALSE otherwise.
+
+--*/
+{
+ CHAR Character;
+ ULONG Count;
+
+ VenPrint(FWUP_YORN_MSG);
+
+ while (ArcGetReadStatus(ARC_CONSOLE_INPUT) != ESUCCESS) {
+ }
+
+ ArcRead(ARC_CONSOLE_INPUT, &Character, 1, &Count);
+ VenPrint1("%c\r\n", Character);
+
+ if ((Character == FWUP_LOWER_Y) || (Character == FWUP_UPPER_Y)) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+#ifdef JENSEN
+
+ARC_STATUS
+JnFsStoreIntoROM(
+ IN PUCHAR FirmwareStart,
+ IN ULONG LowROMBlock,
+ IN ULONG HighROMBlock
+ )
+/*++
+
+Routine Description:
+
+ The firmware update has been read into memory and verified to
+ be correct, and the user has told us to go ahead with the update.
+
+ Operation:
+
+ - Clear the LowROMBlock so that if we are updating the VMS Console,
+ a reboot will bring up the FailSafe Booter.
+
+ - Update the ROM in reverse order, high block -> low block.
+
+ - Verify the ROM against the information in the update buffer.
+
+ - Tells the user to power-cycle the machine if everything is fine.
+
+ - Retries failing blocks, and when retry count is exceeded,
+ asks the user if we should try again.
+
+
+Arguments:
+
+ FirmwareStart A pointer to the beginning of the ROM
+ binary information. This is byte 0 of
+ the low block.
+
+ LowROMBlock The number of the first ROM block to be
+ updated.
+
+ HighROMBlock The number of the last ROM block to be
+ updated.
+
+ HighROMBlock is guaranteed by the caller
+ to be >= LowROMBlock.
+
+Return Value:
+
+ ESUCCESS if update was successful.
+ Otherwise, an error code.
+
+--*/
+{
+ ULONG Count;
+ UCHAR Character;
+ ARC_STATUS Status;
+ BOOLEAN BlockErased[MAXIMUM_NUMBER_ROM_BLOCKS];
+ BOOLEAN BlockStored[MAXIMUM_NUMBER_ROM_BLOCKS];
+ ULONG TempX;
+ ULONG TempY;
+ PUCHAR PromBlockAddress;
+ PUCHAR LocalPromAddress;
+ PCHAR BufferData;
+ PCHAR LocalBufferData;
+ ULONG RetryIndex;
+ ULONG BadCount = 0; // Needed while debugging --- remove later..
+
+ VenClearScreen();
+
+ //
+ // Verify the block arguments
+ //
+
+ if ((LowROMBlock > HighROMBlock) ||
+ (HighROMBlock > (MAXIMUM_NUMBER_ROM_BLOCKS-1))) {
+ return ENODEV;
+ }
+
+ //
+ // Initialize the ROM block status arrays to "not done".
+ //
+
+ for (TempX = LowROMBlock; TempX <= HighROMBlock; TempX++) {
+ BlockErased[TempX] = FALSE;
+ BlockStored[TempX] = FALSE;
+ }
+ //
+ // Determine the type of ROM in the machine.
+ //
+
+ if (FwROMDetermineMachineROMType() != ESUCCESS) {
+ VenPrint(FWUP_UNKNOWN_ROM_MSG);
+ return ENODEV;
+ }
+
+ VenPrint1(FWUP_ROM_TYPE_IS_MSG, MachineROMType);
+
+ //
+ // Erase the low block.
+ //
+
+ VenPrint(FWUP_CLEARING_LOW_PROM_BLOCK_MSG);
+
+ RetryIndex = 0;
+
+ do {
+
+ PromBlockAddress = (PUCHAR)(PROM_VIRTUAL_BASE +
+ (LowROMBlock * SIXTY_FOUR_KB));
+
+ if (!BlockErased[LowROMBlock]) {
+ if (FwROMErase64KB(PromBlockAddress) == ESUCCESS) {
+ BlockErased[LowROMBlock] = TRUE;
+ }
+ }
+
+ //
+ // Now verify that the block has been cleared.
+ //
+
+ for (TempY = 0; TempY < SIXTY_FOUR_KB; TempY++) {
+ if (READ_PORT_UCHAR(PromBlockAddress++) != 0xff) {
+ BlockErased[LowROMBlock] = FALSE;
+ break;
+ }
+ }
+
+
+ //
+ // If the block has not been cleared after ROM_BLOCK_RETRY_COUNT
+ // attempts, ask the user if we should continue trying.
+ //
+
+ RetryIndex++;
+
+ if (!BlockErased[LowROMBlock] &&
+ ((RetryIndex % ROM_BLOCK_RETRY_COUNT) == 0)) {
+
+ VenPrint2(FWUP_BLOCK_CANNOT_BE_ERASED_MSG,
+ LowROMBlock,
+ RetryIndex);
+ VenPrint(FWUP_KEEP_TRYING_MSG);
+ if (!JnFsProceedWithUpdate()) {
+ return EIO;
+ }
+
+ }
+
+ } while (!BlockErased[LowROMBlock]);
+
+ //
+ // Now we write the update into the PROM starting at the highest block.
+ // Reverse writing is used because the serial ROM transfers control to
+ // the VMS console if the checksum of the console is good *and* the
+ // first block is not all 1s. So, if this update includes the VMS console,
+ // we want to write the lowest block last. For other updates (e.g.,
+ // updates to the NT firmware only) it does not matter.
+ //
+
+
+ //
+ // For writes of at least two blocks, start at the high block and
+ // repeatedly try to update every block except the low block.
+ //
+
+ if (HighROMBlock > LowROMBlock) {
+
+ VenPrint(FWUP_CLEARING_AND_WRITING_HIGHER_BLOCKS_MSG);
+
+ RetryIndex = 0;
+
+ do {
+
+ //
+ // Start at the base of the highest block to be written
+ //
+
+ PromBlockAddress = (PUCHAR)(PROM_VIRTUAL_BASE +
+ (HighROMBlock * SIXTY_FOUR_KB));
+ BufferData = FirmwareStart + (HighROMBlock * SIXTY_FOUR_KB) -
+ (LowROMBlock * SIXTY_FOUR_KB);
+
+
+
+ //
+ // TempX > LowROMBlock is intentional, so low block is not updated.
+ //
+
+ for (TempX = HighROMBlock; TempX > LowROMBlock; --TempX) {
+
+ VenPrint(".");
+
+
+ //
+ // Have we cleared and written this block? If not, do so.
+ //
+
+ if (!BlockStored[TempX]) {
+
+
+ //
+ // First erase the block.
+ //
+
+ BlockErased[TempX] = FALSE;
+ if (FwROMErase64KB(PromBlockAddress) == ESUCCESS) {
+ BlockErased[TempX] = TRUE;
+ }
+
+ //
+ // Verify that the block has been erased properly.
+ //
+
+ LocalPromAddress = PromBlockAddress;
+ for (TempY = 0; TempY < SIXTY_FOUR_KB; TempY++) {
+ if (READ_PORT_UCHAR(LocalPromAddress++) != 0xff) {
+ BlockErased[TempX] = FALSE;
+ break;
+ }
+ }
+
+
+ //
+ // Write the block if the erase succeeded.
+ //
+
+ if (BlockErased[TempX]) {
+
+ BlockStored[TempX] = TRUE;
+ LocalPromAddress = PromBlockAddress;
+ LocalBufferData = BufferData;
+
+ for (TempY = 0; TempY < SIXTY_FOUR_KB; TempY++) {
+ if (FwROMByteWrite(LocalPromAddress++, *LocalBufferData++)
+ != ESUCCESS) {
+ BlockStored[TempX] = FALSE;
+ break;
+ }
+ }
+
+ if (BlockStored[TempX]) {
+
+ //
+ // Verify that the writes have succeeded.
+ //
+
+ //
+ // First, set the device(s) to read-mode. To
+ // support devices with a block size smaller than
+ // 64KB, we issues set read-mode commands to every
+ // block within this virtual 64KB block. This is
+ // overkill, but it is easy and quick.
+ //
+
+ LocalPromAddress = PromBlockAddress;
+ for (TempY = 0;
+ TempY < (SIXTY_FOUR_KB / RomValues[MachineROMType].BytesPerBlock);
+ TempY++) {
+ FwROMSetReadMode(LocalPromAddress);
+ LocalPromAddress += RomValues[MachineROMType].BytesPerBlock;
+ }
+
+ LocalPromAddress = PromBlockAddress;
+ LocalBufferData = BufferData;
+
+ for (TempY = 0; TempY < SIXTY_FOUR_KB; TempY++) {
+ if (READ_PORT_UCHAR(LocalPromAddress++) !=
+ *LocalBufferData++) {
+ BlockStored[TempX] = FALSE;
+ break;
+ }
+ }
+ }
+
+ } // if (BlockErased[TempX])
+
+ } // if...
+
+ // Decrement pointers to the next block
+ PromBlockAddress -= SIXTY_FOUR_KB;
+ BufferData -= SIXTY_FOUR_KB;
+
+ } // for...
+
+
+ //
+ // BlockErased[TempX] is TRUE iff the block was erased.
+ // BlockStored[TempX] is TRUE iff the block was erased and stored.
+ //
+
+ RetryIndex++;
+
+ if (AllBlocksNotDone(BlockStored, LowROMBlock+1, HighROMBlock) &&
+ ((RetryIndex % ROM_BLOCK_RETRY_COUNT) == 0)) {
+
+ VenPrint1(FWUP_SOME_BLOCKS_CANNOT_BE_ERASED_MSG,
+ RetryIndex);
+
+ VenPrint(FWUP_ERASE_FAILURES_MSG);
+
+ //
+ // TempX = LowROMBlock+1 is intentional, to not check the
+ // lowest block.
+ //
+
+ for (TempX = LowROMBlock+1; TempX <= HighROMBlock; TempX++) {
+ if (!BlockErased[TempX]) {
+ VenPrint1("%d. ", TempX);
+ }
+ }
+ if (!AllBlocksNotDone(BlockErased, LowROMBlock+1, HighROMBlock)) {
+ VenPrint(FWUP_NONE_MSG);
+ }
+
+
+ VenPrint(FWUP_WRITE_FAILURES_MSG);
+
+ //
+ // TempX = LowROMBlock+1 is intentional, to not check the
+ // lowest block.
+ //
+
+ for (TempX = LowROMBlock+1; TempX <= HighROMBlock; TempX++) {
+ if (!BlockStored[TempX]) {
+ VenPrint1("%d. ", TempX);
+ }
+ }
+ if (!AllBlocksNotDone(BlockStored, LowROMBlock+1, HighROMBlock)) {
+ VenPrint(FWUP_INTERNAL_ERROR_MSG);
+ }
+
+ VenPrint(FWUP_DO_YOU_WISH_TO_KEEP_TRYING_MSG);
+
+ if (!JnFsProceedWithUpdate()) {
+ return EIO;
+ }
+ }
+
+ } while (AllBlocksNotDone(BlockStored, LowROMBlock+1, HighROMBlock));
+ }
+
+ //
+ // Now write the lowest/only block.
+ //
+
+ if (HighROMBlock == LowROMBlock) {
+ VenPrint(FWUP_WRITING_THE_BLOCK_MSG);
+ } else {
+ VenPrint(FWUP_WRITING_THE_LOW_BLOCK_MSG);
+ }
+
+ BlockStored[LowROMBlock] = FALSE;
+ RetryIndex = 0;
+
+ do {
+
+ PromBlockAddress = (PUCHAR)(PROM_VIRTUAL_BASE +
+ (LowROMBlock * SIXTY_FOUR_KB));
+ BufferData = FirmwareStart;
+
+
+ //
+ // First erase the block.
+ //
+
+ BlockErased[LowROMBlock] = FALSE;
+
+ if (FwROMErase64KB(PromBlockAddress) == ESUCCESS) {
+ BlockErased[LowROMBlock] = TRUE;
+ } else {
+ VenPrint(FWUP_BLOCK_CANNOT_BE_ERASED_AFTER_10_MSG);
+ }
+
+
+ //
+ // Verify that the block has been erased.
+ //
+
+ LocalPromAddress = PromBlockAddress;
+
+ for (TempY = 0; TempY < SIXTY_FOUR_KB; TempY++) {
+ if (READ_PORT_UCHAR(LocalPromAddress++) != 0xff) {
+ BlockErased[LowROMBlock] = FALSE;
+ VenPrint(FWUP_ERASURE_VERIFICATION_FAILED_MSG);
+ break;
+ }
+ }
+
+
+ //
+ // Write the block if the erase succeeded.
+ //
+
+ if (BlockErased[LowROMBlock]) {
+
+ BlockStored[LowROMBlock] = TRUE;
+
+ LocalPromAddress = PromBlockAddress;
+ LocalBufferData = BufferData;
+
+ for (TempY = 0; TempY < SIXTY_FOUR_KB; TempY++) {
+ if (FwROMByteWrite(LocalPromAddress++, *LocalBufferData++) != ESUCCESS) {
+ BlockStored[LowROMBlock] = FALSE;
+ break;
+ }
+ }
+
+
+
+ if (BlockStored[LowROMBlock]) {
+
+ //
+ // Verify that the writes have succeeded
+ //
+
+ //
+ // First, set the device(s) to read-mode. To
+ // support devices with a block size smaller than
+ // 64KB, we issues set read-mode commands to every
+ // block within this virtual 64KB block. This is
+ // overkill, but it is easy and quick.
+ //
+
+ LocalPromAddress = PromBlockAddress;
+ for (TempY = 0;
+ TempY < (SIXTY_FOUR_KB / RomValues[MachineROMType].BytesPerBlock);
+ TempY++) {
+ FwROMSetReadMode(LocalPromAddress);
+ LocalPromAddress += RomValues[MachineROMType].BytesPerBlock;
+ }
+
+ LocalPromAddress = PromBlockAddress;
+ LocalBufferData = BufferData;
+
+
+ for (TempY = 0; TempY < SIXTY_FOUR_KB; TempY++) {
+
+ if (READ_PORT_UCHAR(LocalPromAddress++) !=
+ *LocalBufferData++) {
+
+#if 1
+ //
+ // This is temporary debugging assistance for
+ // the ROM update failures. The #if should be
+ // turned off once the problem has been
+ // understood and fixed.
+ //
+
+ PUCHAR TempPromAddress;
+ PCHAR TempBufferData;
+
+ TempPromAddress = LocalPromAddress - 1;
+ TempBufferData = LocalBufferData - 1;
+
+ VenPrint2(FWUP_BAD_DATA_MSG,
+ TempPromAddress,
+ READ_PORT_UCHAR(TempPromAddress)
+ );
+ VenPrint2(FWUP_BUFFER_MSG,
+ TempBufferData,
+ *TempBufferData);
+ BadCount++;
+
+ BlockStored[LowROMBlock] = FALSE;
+
+ if ((BadCount % 5) == 0) {
+ if (!HackGetYesNo()) {
+ break;
+ }
+ }
+#else
+ BlockStored[LowROMBlock] = FALSE;
+ break;
+#endif
+
+ } // if
+
+ } // for
+
+ } // if
+
+ } // if (BlockErased[LowROMBlock])
+
+
+ //
+ // BlockErased[LowROMBlock] is TRUE iff the block was erased.
+ // BlockStored[LowROMBlock] is TRUE iff the block was erased and stored.
+ //
+
+ VenPrint(".");
+ RetryIndex++;
+
+ if (!BlockStored[LowROMBlock] &&
+ ((RetryIndex % ROM_BLOCK_RETRY_COUNT) == 0)) {
+
+ VenPrint1(FWUP_LOW_BLOCK_CANNOT_BE_ERASED_MSG, RetryIndex);
+
+ VenPrint(FWUP_ERASE_FAILURES_MSG);
+
+ if (!BlockErased[LowROMBlock]) {
+ VenPrint1("%d", LowROMBlock);
+ } else {
+ VenPrint(FWUP_NONE_MSG);
+ }
+
+ VenPrint(FWUP_WRITE_FAILURES_MSG);
+ if (!BlockStored[LowROMBlock]) {
+ VenPrint1("%d.", LowROMBlock);
+ } else {
+ VenPrint(FWUP_NONE_MSG);
+ }
+
+ VenPrint(FWUP_DO_YOU_WISH_TO_KEEP_TRYING_MSG);
+
+ if (!JnFsProceedWithUpdate()) {
+ return EIO;
+ }
+ }
+
+ } while (!BlockStored[LowROMBlock]);
+
+
+ //
+ // All done!!
+ //
+
+ return;
+}
+
+BOOLEAN
+AllBlocksNotDone (
+ IN PBOOLEAN StatusArray,
+ IN ULONG StartIndex,
+ IN ULONG EndIndex
+ )
+/*++
+
+Routine Description:
+
+ Returns TRUE if any block has not been "done", where "done"
+ depends on what status array is passed in.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ ULONG X;
+
+ for (X = StartIndex; X <= EndIndex; X++) {
+ if (StatusArray[X] == FALSE) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+#endif // ifdef JENSEN
+
+#ifdef MORGAN
+
+ARC_STATUS
+MorganFsStoreIntoROM(
+ IN ULONG MorganFlashRomChipSelect,
+ IN PUCHAR FirmwareStart,
+ IN ULONG FirmwareBufferLength
+ )
+/*++
+
+Routine Description:
+
+ The firmware update has been read into memory and verified to
+ be correct, and the user has told us to go ahead with the update.
+
+ Operation:
+
+ Morgan strategy differs from Jensen in that the POST and fail-safe
+ loader code resides in a separate jumper-protected FLASH ROM, and
+ that the FLASH ROM containing the Morgan compressed firmware is a bulk
+ erase part with different erase and program methods than the Jensen
+ FLASH ROM parts.
+
+Arguments:
+
+ FirmwareStart A pointer to the beginning of the ROM
+ binary information. This is byte 0 of
+ the Morgan firmware image.
+
+ MorganFlashRomChipSelect Selects which Morgan FLASH ROM the NT
+ will be firmware written into.
+
+ FirmwareBufferLength Length of the Morgan NT firmware image in
+ bytes.
+
+Return Value:
+
+ ESUCCESS if update was successful.
+ Otherwise, an error code.
+
+--*/
+{
+ ARC_STATUS Status;
+
+ VenClearScreen();
+
+ //
+ // Verify the Morgan FLASH ROM chip select value
+ //
+
+
+ if ((MorganFlashRomChipSelect < 1) || (MorganFlashRomChipSelect > 2)) {
+ VenPrint1(FWUP_ROM_CHIP_SELECT_MSG, MorganFlashRomChipSelect);
+ FwWaitForKeypress();
+ return ENODEV;
+ }
+
+ if (MorganBlastFlash( MorganFlashRomChipSelect, FirmwareStart,
+ FirmwareBufferLength) == TRUE) {
+ VenPrint(FWUP_ROM_UPDATE_SUCCEEDED_MSG);
+ FwWaitForKeypress();
+ return ESUCCESS;
+ } else {
+ VenPrint(FWUP_ROM_UPDATE_FAILED_MSG);
+ FwWaitForKeypress();
+ return ENODEV;
+ }
+
+} // MorganFsStoreIntoROM()
+
+#endif // ifdef MORGAN
+
+
+ARC_STATUS
+ReadAndVerifyUpdateFile(
+ IN PCHAR PathName,
+ OUT PULONG BufferAddress,
+ OUT PULONG FirmwareStart,
+ OUT PULONG BufferLength,
+ OUT PULONG LowROMBlock,
+ OUT PULONG HighROMBlock
+ )
+/*++
+
+Routine Description:
+
+ This attempts to load and verify the firmware update file.
+
+Arguments:
+
+ PathName A pointer to string descriptor for the name of
+ the file to load.
+
+ BufferAddress A pointer to a variable that receives the
+ address of the image base.
+
+ FirmwareStart A pointer to a variable that receives the address
+ of the start of the firmware. This is the first
+ byte after the null byte that terminates the
+ identifier string.
+
+ BufferLength A pointer to a variable that receives the length of
+ the image.
+
+ LowROMBlock A pointer to a variable that receives the low ROM
+ block to be updated.
+
+ HighROMBlock A pointer to a variable that receives the low ROM
+ block to be updated.
+
+Return Value:
+
+ ESUCCESS is returned if the image file is loaded and verified.
+
+ Otherwise, an unsuccessful status is returned that describes the
+ reason for failure. Additionally, some detailed error messages
+ may be printed out by this function.
+
+ With any return, the file will have already been closed.
+--*/
+
+{
+
+ ULONG ActualBase;
+ ULONG Count;
+ ULONG FileId;
+ ULONG Index;
+ ULONG PageCount;
+ ARC_STATUS Status;
+ LARGE_INTEGER SeekPosition;
+ FILE_INFORMATION FileInfo;
+ ULONG FileSize;
+ CHAR ChecksumAdjustment[4];
+ ULONG AccumulatedSum;
+ ULONG AmountOfBinaryData;
+
+
+ //
+ // Attempt to open the file.
+ //
+
+ Status = ArcOpen(PathName, ArcOpenReadOnly, &FileId);
+ if (Status != ESUCCESS) {
+ VenPrint(FWUP_READ_CANT_OPEN_MSG);
+ return Status;
+ }
+
+ //
+ // Get the file information to figure out how big the file is.
+ //
+
+ Status = ArcGetFileInformation(FileId, &FileInfo);
+
+ if (Status != ESUCCESS) {
+ VenPrint(FWUP_READ_CANT_GET_FILE_INFO_MSG);
+ ArcClose(FileId);
+ return Status;
+ }
+
+ FileSize = FileInfo.EndingAddress.LowPart - FileInfo.StartingAddress.LowPart;
+
+ if ((FileSize < MINIMUM_UPDATE_FILE_SIZE) || (FileSize > MAXIMUM_UPDATE_FILE_SIZE)) {
+ VenPrint(FWUP_READ_BAD_SIZE_MSG);
+ ArcClose(FileId);
+ return EINVAL;
+ }
+
+
+ //
+ // Compute number of pages in the file and read it in.
+ //
+
+ PageCount = (FileSize + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+ Status = JnFsAllocateDescriptor(MemoryFree, PageCount, &ActualBase);
+
+ if (Status != ESUCCESS) {
+ VenPrint1(FWUP_READ_NOT_ENOUGH_MEMORY, PageCount);
+ ArcClose(FileId);
+ return Status;
+ }
+
+ //
+ // Compute the byte address of the update file buffer
+ //
+ *BufferAddress = KSEG0_BASE | (ActualBase << PAGE_SHIFT);
+ VenPrint(FWUP_READ_READING_MSG);
+ Status = ArcRead(FileId, (PUCHAR)*BufferAddress, FileSize, &Count);
+ ArcClose(FileId);
+
+ if (Count != FileSize) {
+ VenPrint2(FWUP_READ_BAD_READ_COUNT_MSG, FileSize, Count);
+ if (Status != ESUCCESS) {
+ return Status;
+ } else {
+ return EIO;
+ }
+ }
+ if (Status != ESUCCESS) {
+ return Status;
+ }
+
+
+ //
+ // Verify the file's checksum.
+ //
+
+ VenPrint(FWUP_READ_VERIFYING_CHECKSUM_MSG);
+ AccumulatedSum = 0;
+ Index = 0;
+ do {
+ ChecksumAdjustment[0] = ChecksumAdjustment[1];
+ ChecksumAdjustment[1] = ChecksumAdjustment[2];
+ ChecksumAdjustment[2] = ChecksumAdjustment[3];
+ ChecksumAdjustment[3] = *(((PUCHAR)*BufferAddress)+Index);
+ AccumulatedSum += *(((PUCHAR)*BufferAddress)+Index);
+ Index++;
+ } while (Index < FileSize); // Filesize is 1-based, Index is 0-based
+
+ // The last four bytes were really a 32-bit additive-zero checksum,
+ // order of {low byte -- high byte }
+ AccumulatedSum = AccumulatedSum -
+ ChecksumAdjustment[3] -
+ ChecksumAdjustment[2] -
+ ChecksumAdjustment[1] -
+ ChecksumAdjustment[0];
+ AccumulatedSum = AccumulatedSum +
+ ((ChecksumAdjustment[3] << 24) |
+ (ChecksumAdjustment[2] << 16) |
+ (ChecksumAdjustment[1] << 8) |
+ (ChecksumAdjustment[0]));
+
+ if (AccumulatedSum != 0) {
+ VenPrint1 (FWUP_READ_BAD_CHECKSUM_MSG, AccumulatedSum);
+ return ENOEXEC;
+ }
+
+
+ //
+ // The checksum is good. Find the start of the firmware data.
+ //
+
+ Index = 0;
+ while ((Index < MAXIMUM_IDENTIFIER_LENGTH) &&
+ (*(((PUCHAR)*BufferAddress)+Index) != 0)) {
+ Index++;
+ }
+
+ if (Index == MAXIMUM_IDENTIFIER_LENGTH) {
+ VenPrint(FWUP_READ_IDENTIFIER_TOO_LONG_MSG);
+ return ENOEXEC;
+ }
+
+ //
+ // Skip over the starting block byte
+ //
+
+ *FirmwareStart = (ULONG)(((PUCHAR)*BufferAddress) + Index + 2);
+
+
+ //
+ // Now verify legality of the starting block number, and verify that
+ // we have at least that much data in the binary section of the file.
+ //
+
+ *LowROMBlock = *(((PUCHAR)*BufferAddress) + Index + 1);
+
+ if (*LowROMBlock > 0xf) {
+ VenPrint1(FWUP_READ_BAD_START_BLOCK_MSG, *LowROMBlock);
+ return ENOEXEC;
+ }
+
+ AmountOfBinaryData = FileSize -
+ (ULONG)((PUCHAR)*FirmwareStart -
+ (PUCHAR)*BufferAddress) -
+ 4;
+
+ *BufferLength = AmountOfBinaryData;
+
+ if ((AmountOfBinaryData % SIXTY_FOUR_KB) != 0) {
+ VenPrint(FWUP_READ_BAD_BINARY_DATA_MSG);
+ return EBADF;
+ }
+
+ *HighROMBlock = *LowROMBlock + (AmountOfBinaryData / SIXTY_FOUR_KB) - 1;
+
+ if ((*HighROMBlock < *LowROMBlock) || (*HighROMBlock > 0xf)) {
+ VenPrint2(FWUP_READ_TOO_MUCH_DATA_MSG, *LowROMBlock, *HighROMBlock);
+ return E2BIG;
+ }
+
+
+ return ESUCCESS;
+}
+
+ARC_STATUS
+JnFsAllocateDescriptor(
+ IN ULONG MemoryType,
+ IN ULONG PageCount,
+ OUT PULONG ActualBase
+ )
+/*++
+
+Routine Description:
+
+
+ This attempts to find a free section of memory of the requested size
+ and type. It does *not* update the memory descriptor list to reflect a
+ successful allocation.
+
+Arguments:
+
+ MemoryType The type of memory requested.
+
+ PageCount The number of pages requested.
+
+ ActualBase A pointer to a variable that receives the base
+ page number of the found section.
+
+Return Value:
+
+ ESUCCESS is returned if the memory descriptor is found.
+ ENOMEM if not.
+--*/
+
+{
+
+ PMEMORY_DESCRIPTOR MemoryDescriptor;
+ ULONG MemoryBase;
+ ARC_STATUS ReturnStatus = ENOMEM;
+
+ //
+ // Find a memory descriptor of the right size
+ //
+
+ MemoryDescriptor = ArcGetMemoryDescriptor(NULL);
+
+ while (MemoryDescriptor != NULL) {
+ if ((MemoryDescriptor->MemoryType == MemoryType) &&
+ (MemoryDescriptor->PageCount >= PageCount)) {
+ MemoryBase = MemoryDescriptor->BasePage;
+ ReturnStatus = ESUCCESS;
+ break;
+ }
+ MemoryDescriptor = ArcGetMemoryDescriptor(MemoryDescriptor);
+ }
+
+ *ActualBase = MemoryBase;
+
+ return ReturnStatus;
+}
+
+BOOLEAN
+JnFsProceedWithUpdate (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function asks the user if she wants to proceed.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns TRUE if the user typed a Y on the keyboard.
+
+ FALSE if some other key is typed.
+
+--*/
+
+{
+ CHAR Character;
+ ULONG Count;
+ ARC_STATUS Status = EAGAIN;
+
+ VenPrint(FWUP_PRESS_Y_TO_CONTINUE_MSG);
+
+ while (Status != ESUCCESS) {
+ Status = ArcRead(ARC_CONSOLE_INPUT, &Character, 1, &Count);
+ }
+
+ if ((Character == FWUP_LOWER_Y) || (Character == FWUP_UPPER_Y)) {
+ return TRUE;
+ } else {
+ VenPrint(FWUP_UPDATE_ABORTED_MSG);
+ return FALSE;
+ }
+}
+
+
+VOID
+JnFsDecodeBadStatus (
+ IN ARC_STATUS Status
+ )
+/*++
+
+Routine Description:
+
+ This prints out error messages of type ARC_STATUS. ESUCCESS
+ codes cause nothing to be done.
+
+Arguments:
+
+ Status The error code to be decoded.
+
+Return Value:
+
+ None.
+--*/
+
+{
+
+ if (Status != ESUCCESS) {
+
+ if (Status <= EROFS) {
+ VenPrint(FWUP_ERROR_MSG[Status - 1]);
+ } else {
+ VenPrint1(FWUP_ERROR_CODE_MSG, Status);
+ }
+
+ VenPrint(FWUP_UPDATE_ABORTED_MSG);
+ }
+
+ return;
+
+}
+
+
+ARC_STATUS
+FwpFindCDROM (
+ OUT PCHAR PathName
+ )
+/*++
+
+Routine Description:
+
+ This function finds the first CD-ROM in the machine, and returns
+ an ARC pathstring to it.
+
+Arguments:
+
+ PathName A pointer to a buffer area that can receive
+ the CDROM pathname string.
+
+Return Value:
+
+ ESUCCESS if the PathName was loaded.
+
+ Otherwise, an error code. On an error return, PathName is loaded
+ with "scsi(0)cdrom(4)fdisk(0)".
+
+--*/
+{
+ PCONFIGURATION_COMPONENT Controller;
+ BOOLEAN VariableFound = FALSE;
+ ULONG Index;
+
+ for ( Index = 0 ; Index < 8 ; Index++ ) {
+ sprintf(PathName, "scsi(0)cdrom(%d)fdisk(0)", Index);
+ Controller = ArcGetComponent(PathName);
+ if ((Controller != NULL) &&
+ (Controller->Type == FloppyDiskPeripheral)) {
+ VariableFound = TRUE;
+ break;
+ }
+ }
+
+ if (VariableFound) {
+ return (ESUCCESS);
+ } else {
+ sprintf(PathName, "scsi0)cdrom(4)fdisk(0)");
+ return (EIO);
+ }
+}
diff --git a/private/ntos/fw/alpha/jnupdate.h b/private/ntos/fw/alpha/jnupdate.h
new file mode 100644
index 000000000..362199af5
--- /dev/null
+++ b/private/ntos/fw/alpha/jnupdate.h
@@ -0,0 +1 @@
+#define JNUPDATE 1
diff --git a/private/ntos/fw/alpha/jnupstub.c b/private/ntos/fw/alpha/jnupstub.c
new file mode 100644
index 000000000..486e9e123
--- /dev/null
+++ b/private/ntos/fw/alpha/jnupstub.c
@@ -0,0 +1,61 @@
+/*++
+
+Module Name:
+
+ jnupstub.c
+
+Abstract:
+
+ \nt\private\ntos\bldr\alpha\stubs.c variant stub functions for
+ the Jensen update program.
+
+Author:
+
+ John DeRosa 20-Oct-1992
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "ntos.h"
+#include "fwp.h"
+
+
+VOID
+KeBugCheck (
+ IN ULONG BugCheckCode
+ )
+
+/*++
+
+Routine Description:
+
+ This function crashes the system in a controlled manner.
+
+Arguments:
+
+ BugCheckCode - Supplies the reason for the bug check.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Print out the bug check code and halt.
+ //
+
+ VenPrint1("\r\n*** BugCheck (%lx) ***\r\n", BugCheckCode);
+ VenPrint("*** Press any key to reboot the system ***\r\n");
+ FwWaitForKeypress(FALSE);
+ AlphaInstHalt(); // Should never return
+
+ return;
+}
diff --git a/private/ntos/fw/alpha/jnvendor.h b/private/ntos/fw/alpha/jnvendor.h
new file mode 100644
index 000000000..42f7384de
--- /dev/null
+++ b/private/ntos/fw/alpha/jnvendor.h
@@ -0,0 +1,57 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ jnvendor.h
+
+Abstract:
+
+ This module contains vendor-specific Alpha macros.
+
+Author:
+
+ John DeRosa 10-October-1992
+
+Revision History:
+
+--*/
+
+#ifndef _JNVENDOR_
+#define _JNVENDOR_
+
+
+//
+// Print macros.
+//
+
+#define VenClearScreen() \
+ VenPrint1("%c2J", ASCII_CSI)
+
+#define VenMoveCursorToColumn(Spaces) \
+ VenPrint("\r\x9B"#Spaces"C")
+
+#define VenSetScreenColor(FgColor, BgColor) \
+ VenPrint2("%c3%dm", ASCII_CSI, (UCHAR)FgColor); \
+ VenPrint2("%c4%dm", ASCII_CSI, (UCHAR)BgColor)
+
+#define VenSetScreenAttributes( HighIntensity, Underscored, ReverseVideo ) \
+ VenPrint1("%c0m", ASCII_CSI); \
+ if (HighIntensity) { \
+ VenPrint1("%c1m", ASCII_CSI); \
+ } \
+ if (Underscored) { \
+ VenPrint1("%c4m", ASCII_CSI); \
+ } \
+ if (ReverseVideo) { \
+ VenPrint1("%c7m", ASCII_CSI); \
+ }
+
+#define VenSetPosition( Row, Column ) \
+ VenPrint2("%c%d;", ASCII_CSI, Row); \
+ VenPrint1("%dH", Column)
+
+
+#endif // _JNVENDOR_
diff --git a/private/ntos/fw/alpha/jxboot.c b/private/ntos/fw/alpha/jxboot.c
new file mode 100644
index 000000000..6216c4832
--- /dev/null
+++ b/private/ntos/fw/alpha/jxboot.c
@@ -0,0 +1,2251 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ jxboot.c
+
+Abstract:
+
+ This module implements the first pass simple-minded boot program for
+ MIPS and Alpha systems.
+
+Author:
+
+ David N. Cutler (davec) 7-Nov-1990
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ 18-May-1992 John DeRosa [DEC]
+
+ Made Alpha/Jensen modifications.
+
+--*/
+
+#include "fwp.h"
+#include "machdef.h"
+
+#ifdef JENSEN
+#include "jnsnrtc.h"
+#else
+#include "mrgnrtc.h" // morgan
+#endif
+
+#include "string.h"
+#include "led.h"
+#include "fwstring.h"
+#include "xxstring.h"
+
+
+//
+// Define local procedure prototypes.
+//
+
+ARC_STATUS
+FwpFindCDROM (
+ OUT PCHAR PathName
+ );
+
+ARC_STATUS
+FwpEvaluateWNTInstall(
+ OUT PCHAR PathName
+ );
+
+VOID
+FwSetupFloppy(
+ VOID
+ );
+
+VOID
+FwInstallKd(
+ IN VOID
+ );
+
+VOID
+PutLedDisplay(
+ IN UCHAR Value
+ );
+
+ULONG
+SerFwPrint (
+ PCHAR Format,
+ ...
+ );
+
+//
+// Define external references.
+//
+
+#ifdef ALPHA_FW_VDB
+//
+// Debugging Aid
+//
+extern UCHAR DebugAid[3][150];
+#endif
+
+#ifdef ALPHA_FW_SERDEB
+//
+// Variable that enables printing on the COM1 line.
+//
+extern BOOLEAN SerSnapshot;
+#endif
+
+extern ULONG ScsiDebug;
+extern ULONG ProcessorCycleCounterPeriod;
+
+//
+// Global to indicate whether any errors happened during EISA bus config.
+//
+
+BOOLEAN ErrorsDuringEISABusConfiguration;
+
+
+#ifdef ALPHA_FW_KDHOOKS
+
+//
+// Define external data required by the kernel debugger.
+//
+
+CCHAR KeNumberProcessors;
+PKPRCB KiProcessorBlock[MAXIMUM_PROCESSORS];
+KPRCB Prcb;
+KPROCESS Process;
+KTHREAD Thread;
+ULONG KiFreezeFlag = 0;
+BOOLEAN KdInstalled = FALSE;
+LOADER_PARAMETER_BLOCK LoaderBlock;
+KPCR KernelPcr;
+PKTHREAD KiCurrentThread;
+BOOLEAN KiDpcRoutineActiveFlag;
+PKPCR KiPcrBaseAddress;
+PKPRCB KiPrcbBaseAddress;
+PKDEBUG_ROUTINE KiDebugRoutine;
+
+#endif
+
+//
+// Saved sp
+//
+
+ULONG FwSavedSp;
+
+
+//
+// Break into the debugger after loading the program.
+//
+
+BOOLEAN BreakAfterLoad = FALSE;
+
+
+VOID
+FwBootSystem (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is the main ARC firmware code. It displays the
+ boot menu and executes the selected commands.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None. It never returns.
+
+--*/
+
+{
+ ARC_STATUS Status;
+ LONG Index;
+ UCHAR Character;
+ ULONG Count;
+ PCHAR LoadArgv[8];
+ ULONG ArgCount;
+ LONG DefaultChoice = 0;
+ LONG SupplementaryMenuChoice = 0;
+ CHAR PathName[128];
+ CHAR TempName[128];
+ PCHAR TempArgs;
+ CHAR SystemPartition[128];
+ CHAR Osloader[128];
+ CHAR OsloadPartition[128];
+ CHAR OsloadFilename[128];
+ CHAR OsloadOptions[128];
+ CHAR LoadIdentifier[128];
+ CHAR FwSearchPath[128];
+ CHAR ProtectedEnvironmentVariables[5][100];
+ BOOLEAN SecondaryBoot;
+ PCHAR Colon;
+ PCHAR EnvironmentValue;
+ PCHAR LoadEnvp[MAX_NUMBER_OF_ENVIRONMENT_VARIABLES];
+ BOOLEAN Timeout = TRUE;
+ LONG Countdown;
+ ULONG RelativeTime;
+ ULONG PreviousTime;
+ CHAR Choice0[128 + FW_BOOT_MSG_SIZE];
+ CHAR BootChoices[5][128];
+ PCHAR BootMenu[5];
+ ULONG NumberOfBootChoices;
+ GETSTRING_ACTION Action;
+ BOOLEAN VariableFound;
+ PCONFIGURATION_COMPONENT Controller;
+ BOOLEAN TryOpenWithSpecialMod;
+ BOOLEAN RunAProgram;
+ ULONG Problems;
+ UCHAR NVRAMByte;
+ BOOLEAN AutoRunTheECU;
+
+ //
+ // Initialize value for the ALIGN_BUFFER macro.
+ //
+
+ BlDcacheFillSize = KeGetDcacheFillSize();
+
+ //
+ // Initialize the firmware servies.
+ //
+
+ FwInitialize(0);
+ PutLedDisplay(LED_AFTER_FWINITIALIZE);
+
+ //
+ // If the NVRAM AutoRunECU bit is off, do not automatically run the ECU.
+ //
+ // If the NVRAM AutoRunECU bit is on but the machine is not consistent,
+ // clear the AutoRunECU bit and do not automatically run the ECU.
+ //
+ // If the NVRAM AutoRunECU bit is on and the machine is consistent,
+ // clear the AutoRunECU bit and automatically run the ECU.
+ //
+
+ AutoRunTheECU = FALSE;
+
+ //
+ // Load the environment now for FwSystemConsistencyCheck
+ //
+
+ FwEnvironmentLoad();
+
+ PutLedDisplay(LED_ENVIRONMENT_LOADED);
+
+#ifdef ISA_PLATFORM
+
+ //
+ // Warn the user if the system appears to be incapable of booting NT.
+ //
+
+ FwSystemConsistencyCheck (FALSE, &Problems);
+
+#else
+
+ FwpWriteIOChip(RTC_APORT, RTC_RAM_NT_FLAGS0);
+ NVRAMByte = FwpReadIOChip(RTC_DPORT);
+
+ if (((PRTC_RAM_NT_FLAGS_0)(&NVRAMByte))->AutoRunECU) {
+
+ //
+ // AutoRunECU is on.
+ //
+
+ ((PRTC_RAM_NT_FLAGS_0)(&NVRAMByte))->AutoRunECU = 0;
+ FwpWriteIOChip(RTC_APORT, RTC_RAM_NT_FLAGS0);
+ FwpWriteIOChip(RTC_DPORT, NVRAMByte);
+
+ FwSystemConsistencyCheck(TRUE, &Problems);
+
+ //
+ // If there are no other Red problems besides the ECU bit,
+ // run the ECU.
+ //
+
+ if ((Problems &
+ FWP_MACHINE_PROBLEMS_RED &
+ ~FWP_MACHINE_PROBLEMS_ECU) == 0) {
+
+ AutoRunTheECU = TRUE;
+ }
+
+ }
+
+ if (!AutoRunTheECU) {
+
+ //
+ // Warn the user if the system appears to be incapable of booting NT.
+ //
+
+ FwSystemConsistencyCheck(FALSE, &Problems);
+ }
+
+#endif // ISA_PLATFORM
+
+ PutLedDisplay(LED_FW_INITIALIZED);
+
+ while (TRUE) {
+
+ //
+ // Since jnsetup is now part of the firmware, load the environment
+ // variables into the volatile environment.
+ //
+ // HACK: At some point the code should be changed to not use a
+ // volatile environment.
+ //
+
+ FwEnvironmentLoad();
+
+ //
+ // Load up default environment variable values.
+ //
+
+ strcpy(SystemPartition, BootString[SystemPartitionVariable]);
+ strcpy(Osloader, BootString[OsLoaderVariable]);
+ strcpy(OsloadPartition, BootString[OsLoadPartitionVariable]);
+ strcpy(OsloadFilename, BootString[OsLoadFilenameVariable]);
+ strcpy(OsloadOptions, BootString[OsLoadOptionsVariable]);
+ strcpy(LoadIdentifier, BootString[LoadIdentifierVariable]);
+
+ FwGetVariableSegment(0, SystemPartition);
+ FwGetVariableSegment(0, Osloader);
+ FwGetVariableSegment(0, OsloadPartition);
+ FwGetVariableSegment(0, OsloadFilename);
+ FwGetVariableSegment(0, OsloadOptions);
+ FwGetVariableSegment(0, LoadIdentifier);
+
+ if (LoadIdentifier[sizeof("LoadIdentifier=") - 1] != 0) {
+ strcpy(Choice0, FW_BOOT_MSG);
+ strcat(Choice0, &LoadIdentifier[sizeof("LoadIdentifier=") - 1]);
+ BootMenuChoices[0] = Choice0;
+ }
+
+ strcpy(FwSearchPath, "FWSEARCHPATH");
+
+ //
+ // The default action for running a program is to try to open
+ // the specified pathname without a appending .EXE extension first,
+ // and then if that fails, try appending a .EXE extension.
+ //
+
+ TryOpenWithSpecialMod = TRUE;
+
+ FwSetScreenColor( ArcColorWhite, ArcColorBlue);
+ FwSetScreenAttributes( TRUE, FALSE, FALSE);
+
+ //
+ // Add floppy controller to the CDS tree if it is not already there.
+ //
+
+ FwSetupFloppy();
+
+#ifdef EISA_PLATFORM
+
+ //
+ // If we are to automatically run the ECU, jam in some values
+ // and go directly to the run-a-program code.
+ //
+
+ if (AutoRunTheECU) {
+
+ AutoRunTheECU = FALSE;
+ strcpy(PathName, FW_ECU_LOCATION);
+ TempArgs = "";
+ TryOpenWithSpecialMod = FALSE;
+ goto ExecuteImage;
+ }
+
+#endif
+ //
+ // Redisplay whatever menu the user was in (Boot or Supplementary).
+ //
+
+ if (DefaultChoice != 3) {
+
+ //
+ // Display the main boot menu.
+ //
+
+ //
+ // Calculate whether autoboot is active, and if so what the
+ // autoboot value is.
+ //
+
+ if (Timeout &&
+ ((EnvironmentValue = FwGetEnvironmentVariable("Autoload")) != NULL) &&
+ (tolower(*EnvironmentValue) == 'y') &&
+ ((EnvironmentValue = FwGetEnvironmentVariable("Countdown")) != NULL)) {
+ Countdown = atoi(EnvironmentValue);
+
+ } else {
+ Countdown = 0;
+ Timeout = FALSE;
+ }
+
+ DefaultChoice = JzGetSelection(BootMenuChoices,
+ NUMBER_OF_BOOT_CHOICES,
+ DefaultChoice,
+ FW_MENU_BOOT_MSG,
+ NULL,
+ NULL,
+ Countdown,
+ FALSE);
+ }
+
+ //
+ // Here when the user has made a selection, or the user was
+ // previously in the supplementary menu (DefaultChoice == 3) and
+ // so we will return him there, or we are automatically running
+ // the ECU.
+ //
+
+ //
+ // If the selection is not booting the default operating system,
+ // permanently remove the timeout.
+ //
+
+ if (DefaultChoice != 0) {
+ Timeout = FALSE;
+ }
+
+ switch (DefaultChoice) {
+
+ case 0:
+
+ //
+ // Boot default operating system.
+ //
+
+ if (Osloader[sizeof("OSLOADER=") - 1] == 0) {
+ FwSetPosition( 7, 5);
+ FwSetScreenColor(ArcColorRed, ArcColorWhite);
+ FwPrint(FW_NO_BOOT_SELECTIONS_MSG);
+ FwSetScreenColor(ArcColorWhite, ArcColorBlue);
+ FwRead(ARC_CONSOLE_INPUT, &Character, 1, &Count);
+ continue;
+ }
+ strcpy(PathName, &(Osloader[sizeof("OSLOADER=") - 1]));
+ break;
+
+ case 1:
+
+ //
+ // Boot secondary operating system.
+ //
+
+ //
+ // Create the menu.
+ //
+
+ for ( Index = 0 ; Index < 5 ; Index++ ) {
+
+ SecondaryBoot = FwGetVariableSegment(Index, SystemPartition);
+ SecondaryBoot = FwGetVariableSegment(Index, Osloader) ||
+ SecondaryBoot;
+ SecondaryBoot = FwGetVariableSegment(Index, OsloadPartition) ||
+ SecondaryBoot;
+ SecondaryBoot = FwGetVariableSegment(Index, OsloadFilename) ||
+ SecondaryBoot;
+ SecondaryBoot = FwGetVariableSegment(Index, OsloadOptions) ||
+ SecondaryBoot;
+ SecondaryBoot = FwGetVariableSegment(Index, LoadIdentifier) ||
+ SecondaryBoot;
+
+ strcpy(BootChoices[Index], FW_BOOT_MSG);
+ if (LoadIdentifier[sizeof("LOADIDENTIFIER=") - 1] != 0) {
+ strcat(BootChoices[Index],
+ &LoadIdentifier[sizeof("LOADIDENTIFIER=") - 1]);
+ } else {
+ strcat(BootChoices[Index],
+ &OsloadPartition[sizeof("OsloadPartition=") - 1]);
+ strcat(BootChoices[Index],
+ &OsloadFilename[sizeof("OsloadFilename=") - 1]);
+ }
+
+ BootMenu[Index] = BootChoices[Index];
+
+ if (!SecondaryBoot) {
+ break;
+ }
+ }
+
+ //
+ // Check if any selections are available.
+ //
+
+ if ( (Index == 0) && (Osloader[sizeof("OSLOADER=") - 1] == 0) ) {
+ FwSetPosition( 7, 5);
+ FwSetScreenColor(ArcColorRed, ArcColorWhite);
+ FwPrint(FW_NO_BOOT_SELECTIONS_MSG);
+ FwSetScreenColor(ArcColorWhite, ArcColorBlue);
+ FwRead(ARC_CONSOLE_INPUT, &Character, 1, &Count);
+ continue;
+ }
+
+
+ //
+ // Mark the default choice.
+ //
+
+ strcat(BootChoices[0], FW_DEFAULT_MSG);
+
+ //
+ // Display the menu.
+ //
+
+ Index = JzDisplayMenu (BootMenu,
+ Index + 1,
+ (Index ? 1 : 0),
+ 7,
+ 0,
+ FALSE);
+
+ //
+ // Continue if the escape key was pressed.
+ //
+
+ if (Index < 0) {
+ continue;
+ }
+
+ //
+ // Load up the chosen boot selection.
+ //
+
+ FwGetVariableSegment(Index, SystemPartition);
+ FwGetVariableSegment(Index, Osloader);
+ FwGetVariableSegment(Index, OsloadPartition);
+ FwGetVariableSegment(Index, OsloadFilename);
+ FwGetVariableSegment(Index, OsloadOptions);
+
+ strcpy(PathName, &(Osloader[sizeof("OSLOADER=") - 1]));
+ break;
+
+
+ case 2:
+
+ //
+ // Run a program.
+ //
+ //
+ // Get the name.
+ //
+
+ FwSetPosition(5, 0);
+ FwPrint("%cJ", ASCII_CSI); // Clear to end of screen
+ FwPrint(FW_PROGRAM_TO_RUN_MSG);
+ do {
+ Action = JzGetString(TempName,
+ sizeof(TempName),
+ NULL,
+ 5,
+ strlen(FW_PROGRAM_TO_RUN_MSG),
+ FALSE);
+ } while ((Action != GetStringEscape) && (Action != GetStringSuccess));
+
+ //
+ // If no program is specified, continue.
+ //
+
+ if (TempName[0] == 0) {
+ continue;
+ }
+
+ //
+ // Execute monitor if special program name is given.
+ //
+
+ if (strcmp(TempName, MON_INVOCATION_STRING) == 0) {
+
+ FwClearScreen();
+ FwMonitor(3); // goes thru PALcode link routine.
+ continue;
+ }
+
+ //
+ // Strip off any arguments.
+ //
+
+ if ((TempArgs = strchr(TempName, ' ')) != NULL) {
+ *TempArgs++ = 0;
+ } else {
+ TempArgs = "";
+ }
+
+ //
+ // If the name does not contain a "(", then assume it is not a full
+ // pathname.
+ //
+
+ if (strchr( TempName, '(') == NULL) {
+
+ //
+ // If the name contains a semicolon, look for an environment
+ // variable that defines the path.
+ //
+
+ if ((Colon = strchr( TempName, ':')) != NULL) {
+
+ for (Index = 0; TempName[Index] != ':' ; Index++ ) {
+ PathName[Index] = tolower(TempName[Index]);
+ }
+
+ PathName[Index++] = ':';
+ PathName[Index++] = 0;
+ EnvironmentValue = FwGetEnvironmentVariable(PathName);
+ VariableFound = FALSE;
+
+ if (EnvironmentValue != NULL) {
+ strcpy( PathName, EnvironmentValue);
+ VariableFound = TRUE;
+ } else if (!strcmp(PathName, "cd:")) {
+ for ( Index = 0 ; Index < 8 ; Index++ ) {
+ sprintf(PathName, "scsi(0)cdrom(%d)fdisk(0)", Index);
+ Controller = FwGetComponent(PathName);
+ if ((Controller != NULL) && (Controller->Type == FloppyDiskPeripheral)) {
+ VariableFound = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (!VariableFound) {
+ FwSetPosition( 17, 0);
+ FwSetScreenColor(ArcColorRed, ArcColorWhite);
+ FwPrint(FW_PATHNAME_NOT_DEF_MSG);
+ FwWaitForKeypress(TRUE);
+ FwSetScreenColor(ArcColorWhite, ArcColorBlue);
+ continue;
+ } else {
+ strcat( PathName, Colon + 1);
+ }
+
+ } else {
+
+ //
+ // Loop on the FWSEARCHPATH variable.
+ //
+
+ Index = 0;
+ VariableFound = FALSE;
+ do {
+ SecondaryBoot = FwGetVariableSegment(Index++, FwSearchPath);
+ strcpy(PathName, &(FwSearchPath[sizeof("FWSEARCHPATH=") - 1]));
+ strcat(PathName, TempName);
+ if (FwOpen(PathName, ArcOpenReadOnly, &Count) == ESUCCESS) {
+ VariableFound = TRUE;
+ FwClose(Count);
+ break;
+ } else {
+ strcat(PathName, ".exe");
+ if (FwOpen(PathName, ArcOpenReadOnly, &Count) == ESUCCESS) {
+ VariableFound = TRUE;
+ FwClose(Count);
+ break;
+ }
+ }
+ } while (SecondaryBoot);
+
+ if (!VariableFound) {
+ FwSetPosition( 17, 0);
+ FwSetScreenColor(ArcColorRed, ArcColorWhite);
+ FwPrint(FW_ERROR_MSG[ENOENT - 1]);
+ FwWaitForKeypress(TRUE);
+ FwSetScreenColor(ArcColorWhite, ArcColorBlue);
+ continue;
+ }
+
+ }
+
+ } else {
+ strcpy( PathName, TempName);
+ }
+ break;
+
+
+ case 3:
+
+ //
+ // Bring up the supplementary menu
+ //
+
+#ifdef ALPHA_FW_VDB
+ FwVideoStateDump(2);
+#endif
+
+#ifdef ALPHA_FW_SERDEB
+#ifdef ALPHA_FW_VDB
+
+{
+ //
+ // Graphics debugging assistance. Print pre-init and post-init video
+ // state.
+ //
+
+ ULONG H, I, J;
+
+ SerSnapshot = TRUE;
+
+ for (J = 0; J < 8; J++) {
+
+ for (H = 0; H < 3; H++) {
+
+ SerFwPrint("[%d:%d] = ", H, J*16);
+
+ for (I = J*16; I < (J+1)*16; I++) {
+ SerFwPrint("%x ", DebugAid[H][I]);
+ }
+
+ SerFwPrint("\r\n");
+ }
+
+ }
+
+}
+
+#endif
+#endif
+
+
+ SupplementaryMenuChoice = JzGetSelection (SupplementaryMenuChoices,
+ NUMBER_OF_SUPP_CHOICES,
+ SupplementaryMenuChoice,
+ FW_MENU_SUPPLEMENTARY_MSG,
+ NULL,
+ NULL,
+ 0,
+ FALSE);
+
+ FwClearScreen();
+
+ switch (SupplementaryMenuChoice) {
+
+ case 0:
+
+ //
+ // Install new firmware
+ //
+
+ //
+ // If the Jensen update tool is present on the floppy,
+ // run it from there, otherwise run it from CD-ROM.
+ //
+
+ TempArgs = "";
+
+ //
+ // The program string we will attempt to open already has
+ // a .EXE extension, so do not waste type by trying to
+ // open it first without one.
+ //
+
+ TryOpenWithSpecialMod = FALSE;
+
+ FwSetPosition(2, 0);
+ FwPrint(FW_FIRMWARE_UPDATE_SEARCH_MSG);
+
+ if (FwOpen(FW_PRIMARY_FIRMWARE_UPDATE_TOOL,
+ ArcOpenReadOnly,
+ &Count) == ESUCCESS) {
+ FwClose(Count);
+ strcpy(PathName, FW_PRIMARY_FIRMWARE_UPDATE_TOOL);
+ break;
+ } else {
+ FwpFindCDROM(PathName);
+ strcat(PathName, FW_FIRMWARE_UPDATE_TOOL_NAME);
+ break;
+ }
+
+
+ case 1:
+
+ //
+ // Install Windows NT from CD-ROM
+ //
+
+ if (FwpEvaluateWNTInstall(PathName) == ESUCCESS) {
+
+ //
+ // The program string we will attempt to open does not have
+ // a .EXE extension, and it is not supposed to, so do not
+ // waste time trying to open it to see if it is really
+ // there.
+ //
+
+ TryOpenWithSpecialMod = FALSE;
+ TempArgs = "";
+ break;
+
+ } else {
+
+ // We cannot install Windows NT.
+ continue;
+ }
+
+ case 2:
+
+ //
+ // Execute the Jensen Setup Program
+ //
+
+ JensenSetupProgram(&RunAProgram, PathName);
+
+ if (RunAProgram) {
+ TryOpenWithSpecialMod = FALSE;
+ TempArgs = "";
+ break;
+ } else {
+ continue;
+ }
+
+ case 3:
+
+ //
+ // List available devices
+ //
+
+ FwSetPosition(2,0);
+ FwDumpLookupTable();
+ FwPrint(FW_CRLF_MSG);
+ FwWaitForKeypress(TRUE);
+ continue;
+
+ case -1:
+ case 4:
+ default:
+
+ //
+ // Back to boot menu if the escape key was pressed, or
+ // if Return to boot menu was selected, or if something
+ // bad happened in JzDisplayMenu.
+ //
+
+ DefaultChoice = 0;
+ SupplementaryMenuChoice = 0;
+ continue;
+
+ }
+
+ //
+ // If the supplementary menu switch exits, we want to exit the
+ // boot menu switch as well.
+ //
+
+ break;
+
+
+ default:
+
+ //
+ // User hit escape.
+ //
+
+ DefaultChoice = 0;
+ continue;
+
+ }
+
+
+
+
+ExecuteImage:
+
+
+
+ FwClearScreen();
+ FwSetPosition( 0, 0);
+
+
+ //
+ // Get the entire environment.
+ //
+
+ LoadEnvp[0] = FwEnvironmentLoad();
+
+ //
+ // If the environment was loaded, fill out envp.
+ //
+
+ if (LoadEnvp[0] != NULL) {
+
+ Index = 0;
+
+ //
+ // While variables still exist, find the end of each and set
+ // the next envp value to point there. Note this will break
+ // if the last variable has only one null after it.
+ //
+
+ while (*LoadEnvp[Index]) {
+ Index++;
+ LoadEnvp[Index] = strchr(LoadEnvp[Index - 1],'\0') + 1;
+ }
+
+ //
+ // Load the Alpha AXP protected environment variables.
+ //
+
+ if ((Index+1+5) >= MAX_NUMBER_OF_ENVIRONMENT_VARIABLES) {
+ FwSetScreenColor(ArcColorRed, ArcColorWhite);
+ FwPrint(FW_INTERNAL_ERROR_ENVIRONMENT_VARS_MSG);
+ FwSetScreenColor(ArcColorWhite, ArcColorBlue);
+ FwWaitForKeypress(TRUE);
+ } else {
+ strcpy (ProtectedEnvironmentVariables[0],
+ FwGetEnvironmentVariable("PHYSICALADDRESSBITS"));
+ strcpy (ProtectedEnvironmentVariables[1],
+ FwGetEnvironmentVariable("MAXIMUMADDRESSSPACENUMBER"));
+ strcpy (ProtectedEnvironmentVariables[2],
+ FwGetEnvironmentVariable("SYSTEMSERIALNUMBER"));
+ strcpy (ProtectedEnvironmentVariables[3],
+ FwGetEnvironmentVariable("CYCLECOUNTERPERIOD"));
+ strcpy (ProtectedEnvironmentVariables[4],
+ FwGetEnvironmentVariable("PROCESSORPAGESIZE"));
+
+ LoadEnvp[Index++] = ProtectedEnvironmentVariables[0];
+ LoadEnvp[Index++] = ProtectedEnvironmentVariables[1];
+ LoadEnvp[Index++] = ProtectedEnvironmentVariables[2];
+ LoadEnvp[Index++] = ProtectedEnvironmentVariables[3];
+ LoadEnvp[Index++] = ProtectedEnvironmentVariables[4];
+ }
+
+ //
+ // No more, set the last one to NULL.
+ //
+
+ LoadEnvp[Index] = NULL;
+ }
+
+ //
+ // If this is an automatic boot selection, load up the standard
+ // arguments, otherwise load up the command line arguments.
+ //
+
+ LoadArgv[0] = PathName;
+
+ if (DefaultChoice <= 1) {
+
+ ArgCount = 1;
+
+ //
+ // Load up all the Argv parameters.
+ //
+
+ LoadArgv[1] = Osloader;
+ LoadArgv[2] = SystemPartition;
+ LoadArgv[3] = OsloadFilename;
+ LoadArgv[4] = OsloadPartition;
+ LoadArgv[5] = OsloadOptions;
+ LoadArgv[6] = "CONSOLEIN=";
+ LoadArgv[7] = "CONSOLEOUT=";
+
+ //
+ // Find console in and out by looking through the environment.
+ //
+
+ for ( --Index ; Index >= 0 ; Index-- ) {
+ for ( ArgCount = 6; ArgCount <= 7 ; ArgCount++ ) {
+ if (strstr(LoadEnvp[Index],LoadArgv[ArgCount]) == LoadEnvp[Index]) {
+ LoadArgv[ArgCount] = LoadEnvp[Index];
+ }
+ }
+ }
+
+ } else {
+
+ //
+ // Look through the pathname for arguments, by zeroing out any
+ // spaces.
+ //
+
+ Index = 0;
+ ArgCount = 1;
+
+ while (TempArgs[Index] && (ArgCount < MAX_NUMBER_OF_ENVIRONMENT_VARIABLES)) {
+ if (TempArgs[Index] == ' ') {
+ TempArgs[Index] = 0;
+ } else {
+ if (TempArgs[Index - 1] == 0) {
+ LoadArgv[ArgCount++] = &TempArgs[Index];
+ }
+ }
+ Index++;
+ }
+ }
+
+ //
+ // Add a .exe extension if the file is not found in its current form.
+ //
+
+ if (TryOpenWithSpecialMod) {
+ if (FwOpen(PathName, ArcOpenReadOnly, &Count) == ESUCCESS) {
+ FwClose(Count);
+ } else {
+ strcat(PathName, ".exe");
+ }
+ }
+
+ //
+ // Attempt to load the specified file.
+ //
+
+ FwSavedSp = 0;
+
+ Status = FwExecute(PathName, ArgCount, LoadArgv, LoadEnvp);
+
+ //
+ // Close and reopen the console in case it was changed by the user.
+ // Note that we must still check to see if there was a problem
+ // with either the video or keyboard hardware when we first booted.
+ //
+
+ FwClose(ARC_CONSOLE_INPUT);
+ FwClose(ARC_CONSOLE_OUTPUT);
+ FwOpenConsole();
+
+ if (Status == ESUCCESS) {
+
+ //
+ // Pause if returning from a boot. This helps see osloader error
+ // messages.
+ //
+
+ if (DefaultChoice <= 1) {
+ FwPrint(FW_PRESS_ANY_KEY_MSG);
+ FwRead(ARC_CONSOLE_INPUT, &Character, 1, &Count);
+ }
+
+ } else {
+ ParseARCErrorStatus(Status);
+ }
+ }
+}
+
+VOID
+ParseARCErrorStatus(
+ IN ARC_STATUS Status
+ )
+
+/*++
+
+Routine Description:
+
+ This routine prints out an ARC error message and waits until the user
+ hits a key on the keyboard.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR Character;
+ ULONG Count;
+
+ FwSetScreenColor(ArcColorRed, ArcColorWhite);
+ FwPrint(FW_ERROR2_MSG);
+
+ if (Status <= EROFS) {
+ FwPrint(FW_ERROR_MSG[Status - 1]);
+ } else {
+ FwPrint(FW_ERROR_CODE_MSG, Status);
+ }
+
+ FwPrint(FW_PRESS_ANY_KEY2_MSG);
+ FwSetScreenColor(ArcColorWhite, ArcColorBlue);
+ FwRead(ARC_CONSOLE_INPUT, &Character, 1, &Count);
+}
+
+
+
+VOID
+FwErrorTopBoarder(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine clears the screen and prints out the top boarder of a
+ major firwmare error message.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ FwSetPosition(4,5);
+
+ FwPrint("ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»");
+
+}
+
+
+VOID
+FwErrorBottomBoarder(
+ IN ULONG StartAtRow,
+ IN BOOLEAN RedProblems
+ )
+
+/*++
+
+Routine Description:
+
+ This routine prints out the bottom boarder of a major firwmare error
+ message at the current screen position, and then either stall or wait
+ for the user to type a character.
+
+Arguments:
+
+ StartAtRow - The screen row to start outputting at.
+
+ RedProblems - TRUE if Red problems exist.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR Character;
+ ULONG Count;
+
+ FwSetPosition(StartAtRow++, 5);
+ FwPrint("º º");
+
+ if (RedProblems) {
+ FwSetPosition(StartAtRow++, 5);
+ FwPrint(FW_RED_BANNER_PRESSKEY_MSG);
+ }
+
+ FwSetPosition(StartAtRow++, 5);
+ FwPrint("ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ");
+
+ if (RedProblems) {
+ FwRead(ARC_CONSOLE_INPUT, &Character, 1, &Count);
+ } else {
+ FwStallExecution(4 * 1000 * 1000);
+ }
+
+}
+
+
+BOOLEAN
+FwpLookForEISAChildIdentifier(
+ IN PCONFIGURATION_COMPONENT Component,
+ IN PCHAR Identifier
+ )
+
+/*++
+
+Routine Description:
+
+ This looks for a child of Component with an identifier of Identifier.
+
+Arguments:
+
+ Component Pointer to a node in the CDS tree.
+
+ Identifier Identifier string to match against.
+
+
+Return Value:
+
+ TRUE if no match found.
+ FALSE if match found.
+
+--*/
+
+{
+ Component = FwGetChild(Component);
+
+ while (Component != NULL) {
+ if ((Component->IdentifierLength != 0) &&
+ (strcmp(Component->Identifier, Identifier) == 0)) {
+ return (FALSE);
+ }
+ Component = FwGetPeer(Component);
+ }
+
+ return (TRUE);
+}
+
+
+BOOLEAN
+FwpLookForEISAChildClassType(
+ IN PCONFIGURATION_COMPONENT Component,
+ IN CONFIGURATION_CLASS Class,
+ IN CONFIGURATION_TYPE Type
+ )
+
+/*++
+
+Routine Description:
+
+ This looks for a child of Component with a class and type equal to
+ Class and Type.
+
+Arguments:
+
+ Component Pointer to a node in the CDS tree.
+
+ Class The class to match against.
+
+ Type The type to match against.
+
+
+Return Value:
+
+ TRUE if no match found.
+ FALSE if match found.
+
+--*/
+
+{
+ Component = FwGetChild(Component);
+
+ while (Component != NULL) {
+ if ((Component->Class == Class) &&
+ (Component->Type == Type)) {
+ return (FALSE);
+ }
+ Component = FwGetPeer(Component);
+ }
+
+ return (TRUE);
+}
+
+
+VOID
+FwSystemConsistencyCheck (
+ IN BOOLEAN Silent,
+ OUT PULONG Problems
+ )
+
+/*++
+
+Routine Description:
+
+ This routine checks the state of the volatile copies of the ROM firmware
+ data block, and the system time. On an error, it can optionally output
+ an error message.
+
+ A volatile check is made to facilitate using this function in the
+ built-in ROM setup utility. When this is called during the power-up
+ initialization, the volatile areas will not have been loaded if
+ the ROM had a bad checksum, so this indirectly checks the ROM state
+ includint the checksums.
+
+ This consistency check is not exaustive.
+
+Arguments:
+
+ Silent FALSE if messages should be sent to the console.
+ TRUE if this should run silently.
+
+ Problems A pointer to the variable that should receive the
+ indicatation of what problems were found. Zero
+ (0) indicates no problems.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR Floppy;
+ UCHAR Floppy2;
+ PCONFIGURATION_COMPONENT Component;
+ BOOLEAN FoundBootProblems;
+ PTIME_FIELDS SystemTime;
+ ULONG TempX;
+ ULONG Index;
+ ULONG LineNumber;
+
+ *Problems = FWP_MACHINE_PROBLEMS_NOPROBLEMS;
+
+ //
+ // Check system time
+ //
+
+ SystemTime = FwGetTime();
+
+ if ((SystemTime->Year < 1993) ||
+ (SystemTime->Month < 1) || (SystemTime->Month > 12) ||
+ (SystemTime->Day < 1) || (SystemTime->Day > 31) ||
+ (SystemTime->Hour < 0) || (SystemTime->Hour > 23) ||
+ (SystemTime->Minute < 0) || (SystemTime->Minute > 59) ||
+ (SystemTime->Second < 0) || (SystemTime->Second > 59) ||
+ (SystemTime->Milliseconds < 0) || (SystemTime->Milliseconds > 999) ||
+ (SystemTime->Weekday < 0) || (SystemTime->Weekday > 6)) {
+ *Problems = FWP_MACHINE_PROBLEMS_TIME;
+ }
+
+ //
+ // Check environment variables.
+ //
+
+ if (FwGetVolatileEnvironmentVariable("CONSOLEIN") == NULL) {
+ *Problems |= FWP_MACHINE_PROBLEMS_EV;
+ }
+
+ //
+ // Check the CDS
+ //
+
+ Component = FwGetComponent("cpu");
+
+ if ((Component == NULL) ||
+ (Component->Class != ProcessorClass) ||
+ (Component->Type != CentralProcessor)) {
+
+ //
+ // If the CPU node is not valid, then the entire tree is probably bad.
+ //
+
+ *Problems |= FWP_MACHINE_PROBLEMS_CDS;
+ }
+
+ //
+ // Check Floppy environment variables, which are set up by initing
+ // the configuration.
+ //
+
+ if ((FwGetVolatileEnvironmentVariable("FLOPPY") == NULL) ||
+ (FwGetVolatileEnvironmentVariable("FLOPPY2") == NULL)) {
+
+ *Problems |= FWP_MACHINE_PROBLEMS_CDS;
+
+ } else {
+
+ //
+ // Check the first character of the floppy environment variables.
+ //
+
+ Floppy = *FwGetVolatileEnvironmentVariable("FLOPPY");
+ Floppy2 = *FwGetVolatileEnvironmentVariable("FLOPPY2");
+
+ if ((Floppy < '0') || (Floppy > '2') ||
+ ((Floppy2 != 'N') && ((Floppy2 < '0') || (Floppy2 > '2')))) {
+ *Problems |= FWP_MACHINE_PROBLEMS_CDS;
+ }
+ }
+
+ //
+ // Check boot selections
+ //
+
+ JzCheckBootSelections(TRUE, &FoundBootProblems);
+ if (FoundBootProblems) {
+ *Problems |= FWP_MACHINE_PROBLEMS_BOOT;
+ }
+
+#ifdef EISA_PLATFORM
+
+ //
+ // If there were any errors discovered by the EISAini code, or the
+ // minimum required children of the EISA adapter are not present,
+ // indicate an EISA configuration error. The three required children
+ // are the system board, aha1742, and floppy.
+ //
+
+ if (ErrorsDuringEISABusConfiguration == TRUE) {
+
+ *Problems |= FWP_MACHINE_PROBLEMS_ECU;
+ }
+
+ Component = FwGetComponent("eisa()");
+
+ if ((Component == NULL) ||
+ (Component->Class != AdapterClass) ||
+ (Component->Type != EisaAdapter)) {
+
+ *Problems |= FWP_MACHINE_PROBLEMS_CDS;
+ *Problems |= FWP_MACHINE_PROBLEMS_ECU;
+
+ } else {
+
+ //
+ // Look for the three required children of the EISA adapter.
+ //
+
+ //
+ // System board and AHA1742
+ //
+
+ if (FwpLookForEISAChildIdentifier(Component, "DEC2400") ||
+ FwpLookForEISAChildIdentifier(Component, "ADP0002")) {
+ *Problems |= FWP_MACHINE_PROBLEMS_ECU;
+ }
+
+ //
+ // SCSI adapter
+ //
+
+ if (FwpLookForEISAChildClassType(Component,
+ AdapterClass,
+ ScsiAdapter)) {
+ *Problems |= FWP_MACHINE_PROBLEMS_ECU;
+ }
+
+ }
+
+#endif
+
+
+ if (!Silent && (*Problems != FWP_MACHINE_PROBLEMS_NOPROBLEMS)) {
+
+ //
+ // Tell the user what problems were found.
+ //
+
+ FwClearScreen();
+ FwSetScreenColor(ArcColorBlue, ArcColorWhite);
+ FwErrorTopBoarder();
+
+ LineNumber = 5;
+
+ for (Index = 0;
+ Index < FW_SYSTEM_INCONSISTENCY_WARNING_MSG_SIZE;
+ Index++) {
+ FwSetPosition(LineNumber++, 5);
+ FwPrint(FW_SYSTEM_INCONSISTENCY_WARNING_MSG[Index]);
+ }
+
+ TempX = *Problems;
+ Index = 0;
+
+ while (TempX != 0) {
+
+ //
+ // The check against a NULL MachineProblemAreas pointer is for
+ // debugging and could be removed in the final product.
+ //
+
+ if ((((TempX & 1) != 0) || ((TempX & 0x10000) != 0)) &&
+ (MachineProblemAreas[Index] != NULL)) {
+
+ FwSetPosition(LineNumber++,5);
+
+ // For effect, print out all the error areas in yellow.
+ FwPrint("º %c3%dm%s%c3%dm º",
+ ASCII_CSI,
+ ArcColorYellow,
+ MachineProblemAreas[Index],
+ ASCII_CSI,
+ ArcColorBlue);
+ }
+
+ TempX = ((TempX & FWP_MACHINE_PROBLEMS_RED) >> 1) |
+ (((TempX & FWP_MACHINE_PROBLEMS_YELLOW) >> 17) << 16);
+ Index++;
+ }
+
+ //
+ // LineNumber contains the line that we should next print on, and
+ // the screen colors are Blue on White.
+ //
+
+ for (Index = 0;
+ Index < FW_SYSTEM_INCONSISTENCY_WARNING_HOWTOFIX_MSG_SIZE;
+ Index++) {
+ FwSetPosition(LineNumber++, 5);
+ FwPrint(FW_SYSTEM_INCONSISTENCY_WARNING_HOWTOFIX_MSG[Index]);
+ }
+
+ //
+ // Print the bottom of the error message. Stall if only yellow
+ // errors were found, otherwise wait for a keypress.
+ //
+
+ FwErrorBottomBoarder(LineNumber,
+ (*Problems & FWP_MACHINE_PROBLEMS_RED));
+
+ FwSetScreenColor(ArcColorWhite, ArcColorBlue);
+
+ }
+
+ return;
+}
+
+VOID
+FwInitialize (
+ IN ULONG MemSize
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the system parameter block which is located
+ in low memory. This structure contains the firmware entry vector and
+ the restart parameter block. This routine also initializes the io devices,
+ the configuration, and opens standard in/out.
+
+ Note: the system parameter block is initialized early in selftest.c.
+ This was needed in the Jazz code because of how the Jazz video prom code
+ worked; it is mainted here for code compatibility reasons.
+
+Arguments:
+
+ MemSize - Not Used. For compatibility with definitions in bldr\firmware.h
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG Fid;
+ ULONG Index;
+ CHAR DiskPath[40];
+ BOOLEAN BadROMType = FALSE;
+
+ FwPrint(FW_INITIALIZING_MSG);
+
+ //
+ // Initialize Signal vector. And set default signal.
+ //
+// (PARC_SIGNAL_ROUTINE)SYSTEM_BLOCK->FirmwareVector[SignalRoutine] = FwSignal;
+
+ //
+ // Initialize Vendor Must be done before Calling FwAllocatePool. Also
+ // initialize the system ID and time.
+ //
+
+ FwVendorInitialize();
+ FwSystemIdInitialize();
+ FwTimeInitialize();
+
+#ifdef JENSEN
+
+ //
+ // Determine the type of ROM in the machine.
+ //
+
+ if (FwROMDetermineMachineROMType() != ESUCCESS) {
+ FwPrint(FW_UNKNOWN_ROM_MSG);
+ BadROMType = TRUE;
+ }
+
+#endif
+
+ //
+ // Initialize the Fw loadable services.
+ //
+
+ FwLoadInitialize();
+
+ //
+ // Not needed for Jensen, since the SROM disables interrupts.
+ //
+ // Disable the I/O device interrupts.
+ //
+// WRITE_PORT_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Enable,0);
+
+ // Not needed for Alpha/Jensen.
+ //
+ // Initialize the firmware exception handling.
+ // This also enables interrupts in the psr and clears BEV
+ //
+// FwExceptionInitialize();
+
+ //
+ // Initialize the termination function entry points in the transfer vector
+ //
+ FwTerminationInitialize();
+
+ //
+ // Initialize configuration
+ //
+
+ FwConfigurationInitialize();
+
+ //
+ // Initialize the environment.
+ //
+
+ FwEnvironmentInitialize();
+
+ //
+ // Initialize IO structures and display driver.
+ //
+
+ FwIoInitialize1();
+
+ //
+ // Load the environment, because HardDiskInitialize will make a call
+ // to FwSaveConfiguration.
+ //
+
+ FwEnvironmentLoad();
+
+ //
+ // Initialize the I/O services.
+ //
+
+ FwIoInitialize2();
+
+ //
+ // Open the std in and out device. The path name should be taken
+ // from ConsoleIn and ConsoleOut environment variables.
+ //
+ // N.B. FwGetEnvironmentVariable cannot be called again between the
+ // ConsoleName assignment and its use.
+ //
+
+ FwOpenConsole();
+ FwConsoleInitialized = TRUE;
+
+ FwPrint(FW_OK_MSG);
+ FwPrint(FW_CRLF_MSG);
+
+#ifdef ALPHA_FW_KDHOOKS
+
+ //
+ // Break into the debugger if the EisaBreak environment variable
+ // is defined.
+ //
+
+ if (FwGetEnvironmentVariable("EisaBreak") != NULL) {
+ FwPrint("\r\n Breaking into the debugger... \r\n");
+ FwInstallKd();
+ DbgBreakPoint();
+ }
+
+#endif // ALPHA_FW_KDHOOKS
+
+ //
+ // Initialize the EISA routines
+ //
+
+ ErrorsDuringEISABusConfiguration = FALSE;
+ EisaIni();
+
+ if (ErrorsDuringEISABusConfiguration || BadROMType) {
+ FwPrint(FW_CRLF_MSG);
+ FwWaitForKeypress(FALSE);
+ }
+
+ //
+ // Initialize the Restart Block.
+ //
+
+ FwInitializeRestartBlock();
+
+ //
+ // Spin up all of the disks, if necessary.
+ //
+
+ FwPrint(FW_SPIN_DISKS_MSG);
+ for (Index = 0; Index < 8 ; Index++ ) {
+ FwPrint(".");
+ sprintf(DiskPath,"scsi(0)disk(%1d)rdisk(0)partition(0)", Index);
+ if (FwOpen(DiskPath,ArcOpenReadWrite,&Fid) == ESUCCESS) {
+ FwClose(Fid);
+ }
+ }
+ FwPrint(FW_OK_MSG);
+ FwPrint(FW_CRLF_MSG);
+ return;
+}
+
+#ifdef ALPHA_FW_KDHOOKS
+
+VOID
+FwInstallKd(
+ IN VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine installs the kernel debugger exception handlers and
+ initializes it.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ STRING NameString;
+
+ //
+ // Initialize data structures used by the kernel debugger.
+ //
+
+ Prcb.Number = 0;
+ Prcb.CurrentThread = &Thread;
+ KiProcessorBlock[0] = &Prcb;
+ Process.DirectoryTableBase[0] = 0xffffffff;
+ Process.DirectoryTableBase[1] = 0xffffffff;
+ Thread.ApcState.Process = &Process;
+ KeNumberProcessors = 1;
+
+ KiCurrentThread = &Thread;
+ KiDpcRoutineActiveFlag = FALSE;
+ KiPcrBaseAddress = &KernelPcr;
+ KernelPcr.FirstLevelDcacheSize = 0x2000;
+ KernelPcr.FirstLevelDcacheFillSize = 32;
+ KernelPcr.FirstLevelIcacheSize = 0x2000;
+ KernelPcr.FirstLevelIcacheFillSize = 32;
+ KernelPcr.CycleClockPeriod = ProcessorCycleCounterPeriod;
+ KiPrcbBaseAddress = &Prcb;
+
+ KdInitSystem(NULL, FALSE);
+ KdInstalled = TRUE;
+
+ //
+ // Stop in the debugger after asking for the symbols to be loaded.
+ // The computation in the DbgLoadImageSymbols call is because the
+ // kernel debugger cannot read a normal "-rom" linked firmware .exe image,
+ // so a dual was linked without the "-rom" switch. The proper reading
+ // of this file requires a -0x400 offset.
+ //
+
+#ifdef JENSEN
+ RtlInitString(&NameString, "jensfw.exe");
+#endif // JENSEN
+
+#ifdef MORGAN
+ RtlInitString(&NameString, "mrgnfw.exe");
+#endif // MORGAN
+
+ DbgLoadImageSymbols(&NameString, (0x80704000-0x400), (ULONG)-1);
+ DbgBreakPoint();
+}
+
+#endif
+
+
+VOID
+FwOpenConsole(
+ IN VOID
+ )
+/*++
+
+Routine Description:
+
+ This opens the console input and output devices.
+
+Arguments:
+
+ None.
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG Fid;
+ PCHAR ConsoleName;
+
+ //
+ // Open the std in and out device. The path name should be taken
+ // from ConsoleIn and ConsoleOut environment variables.
+ //
+ // N.B. FwGetEnvironmentVariable cannot be called again between the
+ // ConsoleName assignment and its use.
+ //
+
+ if (SerialOutput) {
+ ConsoleName=FW_SERIAL_0_DEVICE;
+ } else {
+ if ((FwGetEnvironmentVariable("ConsoleOut") == NULL) ||
+ ((ConsoleName = FwGetEnvironmentVariable("ConsoleIn")) == NULL)){
+ ConsoleName=FW_KEYBOARD_IN_DEVICE;
+ }
+ }
+
+ if (FwOpen(ConsoleName,ArcOpenReadOnly,&Fid) != ESUCCESS) {
+
+ FwPrint(FW_CONSOLE_IN_ERROR_MSG);
+ FwPrint(FW_CONSOLE_TRYING_TO_OPEN_MSG, FW_KEYBOARD_IN_DEVICE);
+
+ if (FwOpen(FW_KEYBOARD_IN_DEVICE,ArcOpenReadOnly,&Fid) != ESUCCESS) {
+ FwPrint(FW_CONSOLE_IN_FAILSAFE_ERROR_MSG);
+ FwPrint(FW_CONTACT_FIELD_SERVICE_MSG);
+ } else {
+ FwPrint(FW_OK_MSG);
+ FwPrint(FW_CRLF_MSG);
+ FwPrint(FW_CONSOLE_IN_PLEASE_REPAIR_MSG);
+ }
+
+ FwStallExecution(5000000);
+ }
+
+ if (Fid != ARC_CONSOLE_INPUT) {
+ FwPrint(FW_CONSOLE_IN_ERROR2_MSG);
+ }
+
+ if (SerialOutput) {
+ ConsoleName=FW_SERIAL_0_DEVICE;
+ } else {
+ if ((FwGetEnvironmentVariable("ConsoleIn") == NULL) ||
+ ((ConsoleName = FwGetEnvironmentVariable("ConsoleOut")) == NULL)) {
+ ConsoleName=FW_CONSOLE_OUT_DEVICE;
+ }
+ }
+
+ if (FwOpen(ConsoleName,ArcOpenWriteOnly,&Fid) != ESUCCESS) {
+ FwPrint(FW_CONSOLE_OUT_ERROR_MSG);
+ FwPrint(FW_CONSOLE_TRYING_TO_OPEN_MSG, FW_CONSOLE_OUT_DEVICE);
+
+ if (FwOpen(FW_CONSOLE_OUT_DEVICE,ArcOpenWriteOnly,&Fid) != ESUCCESS) {
+ FwPrint(FW_CONSOLE_OUT_FAILSAFE_ERROR_MSG);
+ FwPrint(FW_CONTACT_FIELD_SERVICE_MSG);
+ } else {
+ FwPrint(FW_OK_MSG);
+ FwPrint(FW_CRLF_MSG);
+ FwPrint(FW_CONSOLE_OUT_PLEASE_REPAIR_MSG);
+ }
+
+ FwStallExecution(5000000);
+ }
+
+ if (Fid != ARC_CONSOLE_OUTPUT) {
+ FwPrint(FW_CONSOLE_OUT_ERROR2_MSG);
+ }
+}
+
+VOID
+FwSetupFloppy(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Because the NT floppy driver expects the floppy disk controller node
+ as a child of an EISA or ISA Adapter, and the EISA Configuration Utility
+ deletes all children of the EISA Adapter before it configures the
+ EISA bus, the firmware must add the floppy disk controller information
+ after the ECU has been run on an EISA-based machine. We will also
+ do this on an ISA-based machine to keep the code simple.
+
+ The configuration requirements for the floppy have been stored in
+ environment variables by configuration code in the jnsetcfg.c module.
+
+ This function adds in the floppy nodes, if configuration information
+ exists and the nodes are not already in the tree.
+
+Arguments:
+
+ None.
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+ UCHAR Floppy;
+ UCHAR Floppy2;
+ PCONFIGURATION_COMPONENT FloppyControllerLevel;
+ PCONFIGURATION_COMPONENT FloppyParentAdapterLevel;
+ CONFIGURATION_COMPONENT Component;
+ UCHAR Buffer[sizeof(CM_PARTIAL_RESOURCE_LIST) +
+ (sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * 5) +
+ MAXIMUM_DEVICE_SPECIFIC_DATA];
+ PCM_PARTIAL_RESOURCE_LIST Descriptor = (PCM_PARTIAL_RESOURCE_LIST)&Buffer;
+ ULONG DescriptorSize;
+ CM_FLOPPY_DEVICE_DATA FloppyDeviceData;
+
+ //
+ // Return if:
+ //
+ // If the floppy environment variables do not exist
+ // (FwSystemConsistencyCheck has already reported this).
+ //
+ // If a floppy controller node already exists.
+ //
+ // If the floppy parent node (eg, the EISA adapter on an EISA machine)
+ // does not exist. (FwSystemConsistencyCheck has already reported this.)
+ //
+
+ if ((FwGetEnvironmentVariable("FLOPPY") == NULL) ||
+ (FwGetEnvironmentVariable("FLOPPY2") == NULL) ||
+ (((FloppyControllerLevel = FwGetComponent(FW_FLOPPY_0_DEVICE))
+ != NULL) &&
+ (FloppyControllerLevel->Class == PeripheralClass) &&
+ (FloppyControllerLevel->Type == FloppyDiskPeripheral)) ||
+ ((FloppyParentAdapterLevel = FwGetComponent(FW_FLOPPY_PARENT_NODE)) == NULL)) {
+ return;
+ }
+
+ //
+ // Get the first character of the floppy environment variables.
+ //
+
+ Floppy = *FwGetEnvironmentVariable("FLOPPY");
+ Floppy2 = *FwGetEnvironmentVariable("FLOPPY2");
+
+ //
+ // Now add the floppy controller and one or two peripherals to the
+ // CDS tree.
+ //
+ // This is needed for both non-ECU and ECU-supporting firmware packages
+ // because the NT floppy driver is incapable of finding and parsing
+ // configuration information stored in the Registry at the EISAAdapter
+ // node. All nodes under the EISAAdapter node in the Component Data
+ // Structure are collapsed into one EISAAdapter Registry node by the
+ // CM, so we must hardwire the floppy controller node into the ARC
+ // tree. A side-effect of this is that Jensen can support only one
+ // ISA floppy controller.
+ //
+
+ DescriptorSize =
+ JzMakeDescriptor (Descriptor, // Descriptor
+ TRUE, // Port
+ FLOPPY_ISA_PORT_ADDRESS, // PortStart
+ 8, // PortSize
+ TRUE, // Interrupt
+ CM_RESOURCE_INTERRUPT_LATCHED, // InterruptFlags
+ FLOPPY_LEVEL, // Level
+#ifdef EISA_PLATFORM
+ 0, // Vector
+#else
+ ISA_FLOPPY_VECTOR, // Vector
+#endif
+
+ FALSE, // Memory
+ 0, // MemoryStart
+ 0, // MemorySize
+ TRUE, // Dma
+ FLOPPY_CHANNEL, // Channel
+ FALSE, // SecondChannel
+ FALSE, // DeviceSpecificData
+ 0, // Size
+ NULL // Data
+ );
+
+ JzMakeComponent(&Component,
+ ControllerClass, // Class
+ DiskController, // Type
+ FALSE, // Readonly
+ FALSE, // Removeable
+ FALSE, // ConsoleIn
+ FALSE, // ConsoleOut
+ TRUE, // Input
+ TRUE, // Output
+ 0, // Key
+ DescriptorSize, // ConfigurationDataLength
+ FW_FLOPPY_CDS_IDENTIFIER // Identifier
+ );
+
+ FloppyControllerLevel = FwAddChild(FloppyParentAdapterLevel,
+ &Component,
+ Descriptor);
+
+ //
+ // Add the floppy disk itself as a child of the floppy disk controller.
+ //
+
+ FloppyDeviceData.Version = ARC_VERSION;
+ FloppyDeviceData.Revision = ARC_REVISION;
+
+ //
+ // This switch is tied to the order of the strings in the
+ // FloppyChoices array, defined at the beginning of jnsetmak.c.
+ //
+
+ switch (Floppy) {
+
+ case '0':
+ FloppyDeviceData.Size[0] = '5';
+ FloppyDeviceData.Size[1] = '.';
+ FloppyDeviceData.Size[2] = '2';
+ FloppyDeviceData.Size[3] = '5';
+ FloppyDeviceData.Size[4] = 0;
+ FloppyDeviceData.Size[5] = 0;
+ FloppyDeviceData.Size[6] = 0;
+ FloppyDeviceData.Size[7] = 0;
+ FloppyDeviceData.MaxDensity = 1200;
+ FloppyDeviceData.MountDensity = 0;
+ break;
+
+ case '1':
+ case '2':
+ default:
+ FloppyDeviceData.Size[0] = '3';
+ FloppyDeviceData.Size[1] = '.';
+ FloppyDeviceData.Size[2] = '5';
+ FloppyDeviceData.Size[3] = 0;
+ FloppyDeviceData.Size[4] = 0;
+ FloppyDeviceData.Size[5] = 0;
+ FloppyDeviceData.Size[6] = 0;
+ FloppyDeviceData.Size[7] = 0;
+
+ if (Floppy == '1') {
+ FloppyDeviceData.MaxDensity = 1440;
+ } else {
+ FloppyDeviceData.MaxDensity = 2880;
+ }
+ FloppyDeviceData.MountDensity = 0;
+ break;
+ }
+
+ DescriptorSize =
+ JzMakeDescriptor (Descriptor, // Descriptor
+ FALSE, // Port
+ 0, // PortStart
+ 0, // PortSize
+ FALSE, // Interrupt
+ 0, // InterruptFlags
+ 0, // Level
+ 0, // Vector
+ FALSE, // Memory
+ 0, // MemoryStart
+ 0, // MemorySize
+ FALSE, // Dma
+ 0, // Channel
+ FALSE, // SecondChannel
+ TRUE, // DeviceSpecificData
+ sizeof(CM_FLOPPY_DEVICE_DATA), // Size
+ (PVOID)&FloppyDeviceData // Data
+ );
+
+ JzMakeComponent(&Component,
+ PeripheralClass, // Class
+ FloppyDiskPeripheral, // Type
+ FALSE, // Readonly
+ TRUE, // Removeable
+ FALSE, // ConsoleIn
+ FALSE, // ConsoleOut
+ TRUE, // Input
+ TRUE, // Output
+ 0, // Key
+ DescriptorSize, // ConfigurationDataLength
+ NULL // Identifier
+ );
+
+ FwAddChild( FloppyControllerLevel, &Component, Descriptor );
+
+
+ //
+ // Add a second floppy disk as a child of the floppy disk controller.
+ //
+
+ if (Floppy2 != 'N') {
+
+ FloppyDeviceData.Version = ARC_VERSION;
+ FloppyDeviceData.Revision = ARC_REVISION;
+
+ switch (Floppy2) {
+
+ case '0':
+ FloppyDeviceData.Size[0] = '5';
+ FloppyDeviceData.Size[1] = '.';
+ FloppyDeviceData.Size[2] = '2';
+ FloppyDeviceData.Size[3] = '5';
+ FloppyDeviceData.Size[4] = 0;
+ FloppyDeviceData.Size[5] = 0;
+ FloppyDeviceData.Size[6] = 0;
+ FloppyDeviceData.Size[7] = 0;
+ FloppyDeviceData.MaxDensity = 1200;
+ FloppyDeviceData.MountDensity = 0;
+ break;
+
+ case '1':
+ case '2':
+ default:
+ FloppyDeviceData.Size[0] = '3';
+ FloppyDeviceData.Size[1] = '.';
+ FloppyDeviceData.Size[2] = '5';
+ FloppyDeviceData.Size[3] = 0;
+ FloppyDeviceData.Size[4] = 0;
+ FloppyDeviceData.Size[5] = 0;
+ FloppyDeviceData.Size[6] = 0;
+ FloppyDeviceData.Size[7] = 0;
+ if (Floppy2 == '1') {
+ FloppyDeviceData.MaxDensity = 1440;
+ } else {
+ FloppyDeviceData.MaxDensity = 2880;
+ }
+ FloppyDeviceData.MountDensity = 0;
+ break;
+ }
+
+ DescriptorSize =
+ JzMakeDescriptor (Descriptor, // Descriptor
+ FALSE, // Port
+ 0, // PortStart
+ 0, // PortSize
+ FALSE, // Interrupt
+ 0, // InterruptFlags
+ 0, // Level
+ 0, // Vector
+ FALSE, // Memory
+ 0, // MemoryStart
+ 0, // MemorySize
+ FALSE, // Dma
+ 0, // Channel
+ FALSE, // SecondChannel
+ TRUE, // DeviceSpecificData
+ sizeof(CM_FLOPPY_DEVICE_DATA), // Size
+ (PVOID)&FloppyDeviceData // Data
+ );
+
+ JzMakeComponent(&Component,
+ PeripheralClass, // Class
+ FloppyDiskPeripheral, // Type
+ FALSE, // Readonly
+ TRUE, // Removeable
+ FALSE, // ConsoleIn
+ FALSE, // ConsoleOut
+ TRUE, // Input
+ TRUE, // Output
+ 1, // Key
+ DescriptorSize, // ConfigurationDataLength
+ NULL // Identifier
+ );
+
+ FwAddChild( FloppyControllerLevel, &Component, Descriptor );
+
+ }
+
+ return;
+
+}
+
+ARC_STATUS
+FwpFindCDROM (
+ OUT PCHAR PathName
+ )
+/*++
+
+Routine Description:
+
+ This function finds the first CD-ROM in the machine, and returns
+ an ARC pathstring to it.
+
+Arguments:
+
+ PathName A pointer to a buffer area that can receive
+ the CDROM pathname string.
+
+Return Value:
+
+ ESUCCESS if the PathName was loaded.
+
+ Otherwise, an error code. On an error return, PathName is loaded
+ with "scsi(0)cdrom(4)fdisk(0)".
+
+--*/
+{
+ PCONFIGURATION_COMPONENT Controller;
+ BOOLEAN VariableFound = FALSE;
+ ULONG Index;
+
+ for ( Index = 0 ; Index < 8 ; Index++ ) {
+ sprintf(PathName, "scsi(0)cdrom(%d)fdisk(0)", Index);
+ Controller = FwGetComponent(PathName);
+ if ((Controller != NULL) &&
+ (Controller->Type == FloppyDiskPeripheral)) {
+ VariableFound = TRUE;
+ break;
+ }
+ }
+
+ if (VariableFound) {
+ return (ESUCCESS);
+ } else {
+ sprintf(PathName, "scsi0)cdrom(4)fdisk(0)");
+ return (EIO);
+ }
+}
+
+ARC_STATUS
+FwpEvaluateWNTInstall(
+ OUT PCHAR PathName
+ )
+/*++
+
+Routine Description:
+
+ This function checks to see if this machine is ready to install
+ NT. If so, it finds the SCSI ID of the CD-ROM drive, and returns
+ the pathname to be used.
+
+ If there is a problem, error messages are output to the screen.
+
+Arguments:
+
+ PathName A pointer to a buffer area that can receive
+ the setupldr pathname string.
+
+Return Value:
+
+ ESUCCESS if the PathName string should be used to try to run
+ setupldr.
+
+ Otherwise, an error code.
+
+--*/
+{
+ PCONFIGURATION_COMPONENT Component;
+ ULONG Problems;
+
+ //
+ // If the Red machine state is inconsistent, or there is no CD-ROM,
+ // do an error return.
+ //
+
+ FwSystemConsistencyCheck(FALSE, &Problems);
+
+ if (((Problems & FWP_MACHINE_PROBLEMS_RED) != 0) ||
+ (FwpFindCDROM(PathName) != ESUCCESS)) {
+
+ //
+ // If there are no Red machine consistency problems, we must be
+ // here because FwpFindCDROM gave an error return.
+ //
+
+ if ((Problems & FWP_MACHINE_PROBLEMS_RED) == 0) {
+ FwPrint(FW_NO_CDROM_DRIVE_MSG);
+ }
+
+ FwPrint(FW_WNT_INSTALLATION_ABORTED_MSG);
+ FwWaitForKeypress(FALSE);
+ return (EIO);
+ }
+
+ //
+ // We found the CD-ROM drive. Append the setupldr string to the
+ // CD-ROM string and return.
+ //
+
+ strcat (PathName, "\\alpha\\setupldr");
+ return (ESUCCESS);
+}
diff --git a/private/ntos/fw/alpha/jxconfig.c b/private/ntos/fw/alpha/jxconfig.c
new file mode 100644
index 000000000..8291842dc
--- /dev/null
+++ b/private/ntos/fw/alpha/jxconfig.c
@@ -0,0 +1,1955 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ jxconfig.c
+
+Abstract:
+
+ This module implements the ARC firmware Configuration Query functions as
+ described in the Advanced Risc Computing Specification (Revision 1.00),
+ section 3.3.3.4, for an Alpha/Jensen machine.
+
+Author:
+
+ David M. Robinson (davidro) 13-June-1991
+
+Revision History:
+
+ 30-April-1992 John DeRosa [DEC]
+
+ Added Alpha/Jensen hooks.
+
+
+--*/
+
+#include "fwp.h"
+
+
+#if !defined(FAILSAFE_BOOTER)
+//
+// Define the ARC pathname mnemonics.
+//
+
+PCHAR MnemonicTable[] = {
+ "arc",
+ "cpu",
+ "fpu",
+ "pic",
+ "pdc",
+ "sic",
+ "sdc",
+ "sc",
+ "eisa",
+ "tc",
+ "scsi",
+ "dti",
+ "multi",
+ "disk",
+ "tape",
+ "cdrom",
+ "worm",
+ "serial",
+ "net",
+ "video",
+ "par",
+ "point",
+ "key",
+ "audio",
+ "other",
+ "rdisk",
+ "fdisk",
+ "tape",
+ "modem",
+ "monitor",
+ "print",
+ "pointer",
+ "keyboard",
+ "term",
+ "other",
+ "line",
+ "netper",
+ "memory"
+ };
+#endif // !defined(FAILSAFE_BOOTER)
+
+
+//
+// Function prototypes.
+//
+
+ARC_STATUS
+FwRestoreConfiguration (
+ VOID
+ );
+
+ARC_STATUS
+FwConfigurationCheckChecksum (
+ VOID
+ );
+
+ARC_STATUS
+FwConfigurationSetChecksum(
+ VOID
+ );
+
+ULONG
+FwZeroCompressLength (
+ IN ULONG DataLength,
+ IN PVOID ConfigurationData
+ );
+
+ULONG
+FwZeroCompress (
+ IN ULONG DataLength,
+ IN PVOID ConfigurationData,
+ OUT PVOID OutputBuffer
+ );
+
+VOID
+FwZeroDecompress (
+ IN PVOID InBuffer,
+ IN ULONG Index,
+ OUT PVOID ConfigurationData,
+ IN ULONG Length
+ );
+
+#if !defined(FAILSAFE_BOOTER)
+//
+// IdentifierIndex and DataIndex identify the next free locations in the
+// configuration identifier and data areas. Configuration points to the
+// allocated configuration area.
+//
+
+ULONG IdentifierIndex;
+ULONG DataIndex;
+ULONG EisaDataIndex;
+PCONFIGURATION Configuration;
+#endif // !defined(FAILSAFE_BOOTER)
+
+VOID
+FwConfigurationInitialize (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the configuration area in memory, and the
+ configuration routine addresses.
+
+ Note: This routine is called at phase 1 initialization and
+ at this time nothing is available.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // Initialize the configuration routine addresses in the system
+ // parameter block.
+ //
+
+ (PARC_GET_CHILD_ROUTINE)SYSTEM_BLOCK->FirmwareVector[GetChildRoutine] =
+ FwGetChild;
+ (PARC_GET_PARENT_ROUTINE)SYSTEM_BLOCK->FirmwareVector[GetParentRoutine] =
+ FwGetParent;
+ (PARC_GET_PEER_ROUTINE)SYSTEM_BLOCK->FirmwareVector[GetPeerRoutine] =
+ FwGetPeer;
+ (PARC_ADD_CHILD_ROUTINE)SYSTEM_BLOCK->FirmwareVector[AddChildRoutine] =
+ FwAddChild;
+ (PARC_DELETE_COMPONENT_ROUTINE)SYSTEM_BLOCK->FirmwareVector[DeleteComponentRoutine] =
+ FwDeleteComponent;
+ (PARC_GET_COMPONENT_ROUTINE)SYSTEM_BLOCK->FirmwareVector[GetComponentRoutine] =
+ FwGetComponent;
+ (PARC_GET_DATA_ROUTINE)SYSTEM_BLOCK->FirmwareVector[GetDataRoutine] =
+ FwGetConfigurationData;
+
+#ifndef FAILSAFE_BOOTER
+ (PARC_SAVE_CONFIGURATION_ROUTINE)SYSTEM_BLOCK->FirmwareVector[SaveConfigurationRoutine] =
+ FwSaveConfiguration;
+
+ //
+ // Allocate a region to store the volatile configuration database.
+ //
+
+ Configuration = (PCONFIGURATION)FwAllocatePool(sizeof(CONFIGURATION));
+
+ //
+ // Initialize other static data and restore the configuration from ROM.
+ //
+
+ FwRestoreConfiguration();
+#endif
+
+ return;
+}
+
+PCONFIGURATION_COMPONENT
+FwAddChild (
+ IN PCONFIGURATION_COMPONENT Component,
+ IN PCONFIGURATION_COMPONENT NewComponent,
+ IN PVOID ConfigurationData OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This routine adds a new component entry as a child of Component, including
+ an identifier string if the IdentifierLength field of NewComponent is
+ non-zero, and configuration data if the ConfigurationDataLength field of
+ NewComponent is non-zero and the ConfigurationData parameter is present.
+ If Component is NULL, the root component is being added.
+
+Arguments:
+
+ Component - Supplies a pointer to a configuration component.
+
+ NewComponent - Supplies a pointer to a new configuration component
+ to be added as a child of Component.
+
+ ConfigurationData - Supplies an optional pointer to a configuration
+ data buffer.
+
+Return Value:
+
+ Returns a pointer to the new configuration component entry. If the
+ create operation was unsuccessful, NULL is returned.
+
+--*/
+{
+#ifndef FAILSAFE_BOOTER
+
+ PCONFIGURATION_PACKET Packet;
+ PCONFIGURATION_PACKET ParentPacket;
+ ULONG Index;
+ PUCHAR String;
+ PUCHAR Data;
+ BOOLEAN Eisa;
+ ULONG DataLength;
+
+ //
+ // If Component is NULL and the new Class is system, the root component is
+ // being added, otherwise find the first free component entry.
+ //
+
+ if ((Component == NULL) && (NewComponent->Class == SystemClass)) {
+
+ Packet = &Configuration->Packet[0];
+
+ //
+ // TEMPTEMP If the root component is being added, clear all of the
+ // configuration area. This is a Hack, should be replaced by
+ // a good way to do this.
+ //
+
+ RtlZeroMemory(Configuration, sizeof(CONFIGURATION));
+ IdentifierIndex = 0;
+ DataIndex = 0;
+ EisaDataIndex = 0;
+
+ } else {
+
+ Packet = &Configuration->Packet[1];
+
+ for ( Index = 1 ; Packet->Parent != NULL ; Index++ ) {
+
+ //
+ // If no more entries, return NULL. Since Index is 0 based
+ // subtract one from NUMBER_OF_ENTRIES for end check.
+ //
+
+ if (Index >= (NUMBER_OF_ENTRIES - 1)) {
+ return NULL;
+ }
+
+ Packet++;
+ }
+ }
+
+
+ //
+ // Check to see if the parent component is the eisa bus.
+ //
+
+ if ((Component != NULL) && (Component->Type == EisaAdapter)) {
+ Eisa = TRUE;
+ } else {
+ Eisa = FALSE;
+ }
+
+ //
+ // If there is not enough space for the new identifier string or the
+ // configuration data, return NULL.
+ //
+
+ if (IdentifierIndex + NewComponent->IdentifierLength >= LENGTH_OF_IDENTIFIER) {
+ return(NULL);
+ }
+
+ if (Eisa) {
+ DataLength = FwZeroCompressLength(NewComponent->ConfigurationDataLength,
+ ConfigurationData);
+
+ if (EisaDataIndex + DataLength >= LENGTH_OF_EISA_DATA) {
+ return(NULL);
+ }
+ } else {
+ if (DataIndex + NewComponent->ConfigurationDataLength >= LENGTH_OF_DATA) {
+ return(NULL);
+ }
+ }
+
+ //
+ // There is space for everything. Fill in new configuration entry first.
+ //
+
+ Packet->Component.Class = NewComponent->Class;
+ Packet->Component.Type = NewComponent->Type;
+ Packet->Component.Flags = NewComponent->Flags;
+ Packet->Component.Version = NewComponent->Version;
+ Packet->Component.Revision = NewComponent->Revision;
+ Packet->Component.Key = NewComponent->Key;
+ Packet->Component.AffinityMask = 0xffffffff;
+ Packet->Component.IdentifierLength = NewComponent->IdentifierLength;
+ Packet->Component.Identifier = &Configuration->Identifier[IdentifierIndex];
+
+ //
+ // If Component is NULL, this is the root component so the parent is NULL,
+ // otherwise find the parent packet.
+ //
+
+ if (Component == NULL) {
+ ParentPacket = NULL;
+ } else {
+ ParentPacket = CONTAINING_RECORD(Component,
+ CONFIGURATION_PACKET,
+ Component);
+ }
+
+ //
+ // Only copy configuration data length if configuration data is supplied.
+ //
+
+ if (ConfigurationData != NULL) {
+ Packet->Component.ConfigurationDataLength =
+ NewComponent->ConfigurationDataLength;
+ } else {
+ Packet->Component.ConfigurationDataLength = 0;
+ }
+
+ Packet->Parent = ParentPacket;
+
+ Packet->Child = NULL;
+
+ //
+ // Add identifer string.
+ //
+
+ String = NewComponent->Identifier;
+
+ for ( Index = 0 ; Index < NewComponent->IdentifierLength ; Index++ ) {
+ Configuration->Identifier[IdentifierIndex++] = *String++;
+ }
+
+ //
+ // Make sure identifier is zero terminated, if not add one.
+ //
+
+ if (Configuration->Identifier[IdentifierIndex - 1] != 0) {
+ Configuration->Identifier[IdentifierIndex++] = 0;
+ Packet->Component.IdentifierLength += 1;
+ }
+
+ //
+ // Copy configuration data.
+ //
+
+ if (Eisa) {
+ Packet->ConfigurationData = &Configuration->EisaData[EisaDataIndex];
+ EisaDataIndex += FwZeroCompress(NewComponent->ConfigurationDataLength,
+ ConfigurationData,
+ &Configuration->EisaData[EisaDataIndex]);
+ } else {
+ Data = (PUCHAR)ConfigurationData;
+ Packet->ConfigurationData = &Configuration->Data[DataIndex];
+ for ( Index = 0 ; Index < NewComponent->ConfigurationDataLength ; Index++ ) {
+ Configuration->Data[DataIndex++] = *Data++;
+ }
+ }
+
+ //
+ // Add the new component as the first child of Component, unless this is
+ // the root component.
+ //
+
+ if (Component == NULL) {
+ Packet->Peer = NULL;
+ } else {
+ Packet->Peer = ParentPacket->Child;
+ ParentPacket->Child = Packet;
+ }
+
+ return (&Packet->Component);
+
+#else // FAILSAFE_BOOTER
+
+ return NULL;
+
+#endif // ndef FAILSAFE_BOOTER
+}
+
+ARC_STATUS
+FwDeleteComponent (
+ IN PCONFIGURATION_COMPONENT Component
+ )
+
+/*++
+
+Routine Description:
+
+ This function deletes a component entry. If the entry has one or more
+ children, an error is returned, otherwise the entry is deleted. Deleting
+ the entry will implicitly delete the identifier string and the configuration
+ data.
+
+ Note that no attempt is made to compress the entry, identifier, or the
+ configuration data areas after an entry is deleted, as doing so would
+ potentially invalidate outstanding pointers.
+
+Arguments:
+
+ Component - Supplies a pointer to a configuration component.
+
+Return Value:
+
+ Returns ESUCCESS if the entry was successfully deleted, otherwise one of
+ the following error codes is returned.
+
+ EINVAL Component is not a valid configuration component.
+
+ EACCES Component has children, and cannot be freed until they
+ are deleted.
+
+
+--*/
+{
+#ifndef FAILSAFE_BOOTER
+
+ PCONFIGURATION_PACKET Packet;
+ PCONFIGURATION_PACKET SearchPacket;
+
+ if (Component == NULL) {
+ return EINVAL;
+ }
+
+ Packet = CONTAINING_RECORD(Component,
+ CONFIGURATION_PACKET,
+ Component);
+
+ //
+ // If Component's Parent field is NULL, return EINVAL.
+ //
+
+ if (Packet->Parent == NULL) {
+ return EINVAL;
+ }
+
+ //
+ // If Component has children, return EACCES.
+ //
+
+ if (Packet->Child != NULL) {
+ return EACCES;
+ }
+
+
+ //
+ // Find the entry that points to Component, and point it to
+ // Component's peer. If this is Component's parent, update the child
+ // pointer, otherwise this is a peer and update the peer pointer.
+ //
+
+ SearchPacket = Packet->Parent;
+
+ if (SearchPacket->Child == Packet) {
+ SearchPacket->Child = Packet->Peer;
+ } else {
+ SearchPacket = SearchPacket->Child;
+ while (SearchPacket->Peer != Packet) {
+ SearchPacket = SearchPacket->Peer;
+ }
+ SearchPacket->Peer = Packet->Peer;
+ }
+
+ //
+ // Delete Component by zeroing the parent pointer.
+ //
+
+ Packet->Parent = NULL;
+
+ return ESUCCESS;
+
+#else // FAILSAFE_BOOTER
+ return EINVAL;
+
+#endif // ndef FAILSAFE_BOOTER
+}
+
+
+#ifndef FAILSAFE_BOOTER
+
+PCONFIGURATION_COMPONENT
+FwCoreGetComponent (
+ IN PCHAR Pathname,
+ IN PCONFIGURATION_COMPONENT MatchComponent
+ )
+/*++
+
+Routine Description:
+
+ This function does the work for FwGetComponent.
+
+Arguments:
+
+ Pathname - Supplies a string containing the pathname to search.
+
+ MatchComponent - A pointer to the current node in the tree in the
+ recursive search.
+
+Return Value:
+
+ Returns a pointer to the configuration component that best matches
+ pathname.
+
+ Algorithm:
+
+ If MatchComponent == NULL, return NULL.
+
+ else..
+
+ Check this node. If a successful match, then:
+ - if we are at the end of the Pathname, return this node.
+ - otherwise, check the children of this node for the
+ remainder of the pathname.
+
+ If there is a better match in one of the children,
+ return that pointer. Else, return the pointer to this node.
+
+ else..
+
+ Check the peers of this node. If a successful match is returned
+ back, return the pointer returned.
+
+ else..
+
+ return NULL.
+
+--*/
+{
+
+ PCONFIGURATION_COMPONENT Component;
+ PCHAR MatchString;
+ PCHAR Token;
+ ULONG Key;
+ BOOLEAN NodeMatch = FALSE;
+
+ if (MatchComponent == NULL) {
+ return NULL;
+ }
+
+ //
+ // Check this node.
+ //
+
+ Token = Pathname;
+ MatchString = MnemonicTable[MatchComponent->Type];
+
+ //
+ // Compare strings.
+ //
+
+ while ((*MatchString == tolower(*Token)) &&
+ (*MatchString != 0)){
+ MatchString++;
+ Token++;
+ }
+
+ //
+ // Strings compare if the first mismatch is the terminator for each.
+ //
+
+ if ((*MatchString == 0) &&
+ ((*Token == '(') || (*Token == 0))) {
+
+ //
+ // Form key.
+ //
+
+ Key = 0;
+ if (*Token == '(') {
+ Token++;
+ }
+ while ((*Token != ')') && (*Token != 0)) {
+ Key = (Key * 10) + *Token++ - '0';
+ }
+
+ //
+ // If the key matches the component matches, we have a match.
+ //
+
+ if (MatchComponent->Key == Key) {
+ NodeMatch = TRUE;
+ }
+ }
+
+ if (NodeMatch) {
+
+ //
+ // This node matches the first component specified in Pathname.
+ // Token points at either a ')' or the NULL terminating the
+ // Pathname string.
+ //
+
+ if ((*Token == 0) ||
+ ((*Token == ')' && (*(Token+1) == 0)))
+ ) {
+
+ return MatchComponent;
+
+ } else {
+
+ Component = FwCoreGetComponent (Token+1,
+ FwGetChild(MatchComponent)
+ );
+ if (Component == NULL) {
+ return MatchComponent;
+ } else {
+ return Component;
+ }
+
+ }
+
+ } else {
+
+ //
+ // This node does not match our current location in the String.
+ // Check the peers.
+ //
+ // If the search fails with the peers of this node, NULL will be
+ // returned, which is what we want to return from this call as well.
+ //
+
+ return FwCoreGetComponent(Pathname, FwGetPeer(MatchComponent));
+ }
+}
+
+#endif // ndef FAILSAFE_BOOTER
+
+
+PCONFIGURATION_COMPONENT
+FwGetComponent (
+ IN PCHAR Pathname
+ )
+
+/*++
+
+Routine Description:
+
+ This routine searches the configuration tree for the component that best
+ matches the Pathname string.
+
+Arguments:
+
+ Pathname - Supplies a string containing the pathname to search.
+
+Return Value:
+
+ Returns a pointer to the configuration component that best matches
+ pathname.
+
+
+--*/
+{
+#ifndef FAILSAFE_BOOTER
+
+ PCONFIGURATION_COMPONENT Component;
+
+ //
+ // Start searching from the first child of the root component.
+ //
+
+ if ((Component = FwCoreGetComponent(Pathname,
+ FwGetChild(FwGetChild(NULL))))
+ != NULL) {
+ return Component;
+ } else {
+ return FwGetChild(NULL);
+ }
+
+#else // FAILSAFE_BOOTER
+
+ return NULL;
+
+#endif // ndef FAILSAFE_BOOTER
+
+}
+
+
+PCONFIGURATION_COMPONENT
+FwGetChild (
+ IN PCONFIGURATION_COMPONENT Component OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ Returns a pointer to the configuration component for the first child of
+ Component. If Component is NULL, a pointer to the root configuration
+ component is returned.
+
+Arguments:
+
+ Component - Supplies an optional pointer to a configuration component.
+
+Return Value:
+
+ Returns a pointer to the configuration component for the first child of
+ Component. If Component has no children, this pointer will be NULL. If
+ Component is NULL, a pointer to the root configuration component is
+ returned.
+
+--*/
+{
+#ifndef FAILSAFE_BOOTER
+
+ PCONFIGURATION_PACKET Packet;
+
+ if (Component == NULL) {
+ return &Configuration->Packet[0].Component;
+ } else {
+ Packet = CONTAINING_RECORD(Component,
+ CONFIGURATION_PACKET,
+ Component);
+
+ return &((PCONFIGURATION_PACKET)(Packet->Child))->Component;
+ }
+
+#else // FAILSAFE_BOOTER
+
+ return NULL;
+
+#endif // ndef FAILSAFE_BOOTER
+}
+
+PCONFIGURATION_COMPONENT
+FwGetParent (
+ IN PCONFIGURATION_COMPONENT Component
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the parent of the named component.
+
+Arguments:
+
+ Component - Supplies a pointer to a configuration component.
+
+Return Value:
+
+ Returns a pointer to the configuration component for the parent of
+ Component. If Component has no parent NULL is returned (this is only
+ true for the root configuration component).
+
+--*/
+{
+
+#ifndef FAILSAFE_BOOTER
+
+ PCONFIGURATION_PACKET Packet;
+
+ Packet = CONTAINING_RECORD(Component,
+ CONFIGURATION_PACKET,
+ Component);
+
+ if (Packet->Parent == NULL) {
+ return NULL;
+ } else {
+ return &((PCONFIGURATION_PACKET)(Packet->Parent))->Component;
+ }
+
+#else // FAILSAFE_BOOTER
+
+ return NULL;
+
+#endif // FAILSAFE_BOOTER
+}
+
+PCONFIGURATION_COMPONENT
+FwGetPeer (
+ IN PCONFIGURATION_COMPONENT Component
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the peer of the named component.
+
+Arguments:
+
+ Component - Supplies a pointer to a configuration component.
+
+Return Value:
+
+ Returns a pointer to the configuration component for the next peer of
+ Component. If Component has no next peer, NULL is returned.
+
+--*/
+{
+#ifndef FAILSAFE_BOOTER
+
+ PCONFIGURATION_PACKET Packet;
+
+ Packet = CONTAINING_RECORD(Component,
+ CONFIGURATION_PACKET,
+ Component);
+
+ if (Packet->Peer == NULL) {
+ return NULL;
+ } else {
+ return &((PCONFIGURATION_PACKET)(Packet->Peer))->Component;
+ }
+
+#else // FAILSAFE_BOOTER
+
+ return NULL;
+
+#endif // ndef FAILSAFE_BOOTER
+}
+
+#ifndef FAILSAFE_BOOTER
+ARC_STATUS
+FwGetConfigurationDataIndex(
+ OUT PVOID ConfigurationData,
+ IN PCONFIGURATION_COMPONENT Component,
+ IN ULONG Index,
+ IN ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the specified configuration data
+ associated with Component in the buffer supplied by
+ ConfigurationData. The max length of the data is stored
+ in the Component structure.
+
+Arguments:
+
+ ConfigurationData - Supplies a pointer to a buffer to receive the
+ configuration data.
+
+ Component - Supplies a pointer to a configuration component.
+
+ Index - Supplies an index within the configuration data.
+
+ Length - Supplies the number of bytes to read (see the
+ ConfigurationDataLength field within the Component for the max
+ value).
+
+Return Value:
+
+ If the configuration data is successfully copied into the buffer
+ provided by ConfigurationData, ESUCCESS is returned. Otherwise one of
+ the following error codes is returned.
+
+ EINVAL Component is not a valid configuration component or the
+ other arguments are invalid.
+
+--*/
+
+{
+ PCONFIGURATION_PACKET Packet;
+ ULONG DataSize;
+ PUCHAR SourceData;
+ PUCHAR DestinationData;
+
+ DataSize = Component->ConfigurationDataLength;
+
+ //
+ // check the passing parameters
+ //
+
+ if ( DataSize == 0 || Index >= DataSize || DataSize - Index < Length ) {
+ return EINVAL;
+ }
+
+ Packet = CONTAINING_RECORD( Component, CONFIGURATION_PACKET, Component );
+
+ //
+ // If Component's Parent field is NULL, return EINVAL.
+ //
+
+ if (Packet->Parent == NULL) {
+ return EINVAL;
+ }
+
+ //
+ // If this is an eisa component, decompress the data, otherwise just copy it.
+ //
+
+ if (Packet->Parent->Component.Type == EisaAdapter) {
+ FwZeroDecompress(Packet->ConfigurationData,
+ Index,
+ ConfigurationData,
+ Length);
+
+ } else {
+ SourceData = (PUCHAR)Packet->ConfigurationData + Index;
+ DestinationData = ConfigurationData;
+
+ while ( Length-- )
+ {
+ *DestinationData++ = *SourceData++;
+ }
+ }
+
+ return ESUCCESS;
+}
+#endif // ndef FAILSAFE_BOOTER
+
+ARC_STATUS
+FwGetConfigurationData (
+ OUT PVOID ConfigurationData,
+ IN PCONFIGURATION_COMPONENT Component
+ )
+
+/*++
+
+Routine Description:
+
+ This functions returns the configuration data associated with Component
+ in the buffer supplied by ConfigurationData. The length of the data
+ is stored in the Component structure.
+
+Arguments:
+
+ ConfigurationData - Supplies a pointer to a buffer to receive the
+ configuration data.
+
+ Component - Supplies a pointer to a configuration component.
+
+Return Value:
+
+ If the configuration data is successfully copied into the buffer
+ provided by ConfigurationData, ESUCCESS is returned. Otherwise one of
+ the following error codes is returned.
+
+ EINVAL Component is not a valid configuration component.
+
+--*/
+
+{
+#ifndef FAILSAFE_BOOTER
+ return(FwGetConfigurationDataIndex(ConfigurationData,
+ Component,
+ 0,
+ Component->ConfigurationDataLength));
+#else
+
+ return EINVAL;
+
+#endif
+}
+
+#if !defined(FAILSAFE_BOOTER)
+ARC_STATUS
+FwEnvironmentStore (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This loads the entire environment into the non-volatile environment area.
+
+ Alpha/Jensen uses a segmented block-erase PROM. When the code wants
+ to store one environment variable, it must store all of them.
+
+ This routine must *only* be called from FwSaveConfiguration, which
+ does the block-erase and the store of the other part of the
+ non-volatile configuration information.
+
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ ESUCCESS if the writes were OK.
+ EIO otherwise.
+
+--*/
+
+{
+ ULONG Index;
+ PNV_CONFIGURATION NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
+ PUCHAR NvChars, VChars;
+
+
+ VChars = VolatileEnvironment;
+ NvChars = (PUCHAR)&NvConfiguration->Environment[0];
+
+ for (Index = 0; Index < LENGTH_OF_ENVIRONMENT; Index++) {
+ if (FwROMByteWrite(NvChars++, *VChars++) != ESUCCESS) {
+ return EIO;
+ }
+ }
+
+ if (FwEnvironmentSetChecksum() != ESUCCESS) {
+ return EIO;
+ } else {
+ return ESUCCESS;
+ }
+}
+#endif // !defined(FAILSAFE_BOOTER)
+
+ARC_STATUS
+FwSaveConfiguration (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine stores all of the configuration entries into NVRAM,
+ including the associated identifier strings and configuration data.
+
+ Alpha/Jensen saves the entire configuration structure, i.e.
+ including the environment variables, because the ARC CDS + environment
+ variables are all in one structure and Jensen has a segmented
+ block-erase PROM. Doing a complete save changes the least code.
+
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns ESUCCESS if the save completed successfully, otherwise one of the
+ following error codes is returned.
+
+ ENOSPC Not enough space in the NVRAM to save all of the data.
+
+ EIO Some write error happened in the PROM.
+
+--*/
+
+{
+
+#ifndef FAILSAFE_BOOTER
+
+ ULONG EntryIndex;
+ ULONG Index;
+ PCONFIGURATION_PACKET Packet;
+ PCONFIGURATION_COMPONENT Component;
+ PNV_CONFIGURATION NvConfiguration;
+ COMPRESSED_CONFIGURATION_PACKET CompressedPacket;
+ USHORT NvIdentifierIndex;
+ USHORT NvDataIndex;
+ USHORT NvEisaDataIndex;
+ PUCHAR CompressedChars, NvChars, Data;
+
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
+ NvIdentifierIndex = 0;
+ NvDataIndex = 0;
+ NvEisaDataIndex = 0;
+
+
+
+#ifdef JENSEN
+ //
+ // Erase the PROM block we are going to update.
+ //
+ // N.B. This call erases one block in the underlying ROM set. Therefore,
+ // the block size of the ROM had better be at least the size of the
+ // ARC data to be written.
+ //
+
+ if (FwROMEraseBlock((PUCHAR)NVRAM_CONFIGURATION) != ESUCCESS) {
+ return ENOSPC;
+ }
+#endif
+
+ //
+ // Write each volatile packet into a compressed non-volatile packet,
+ // including the identifier string and the configuration data.
+ //
+
+ for ( EntryIndex = 0 ; EntryIndex < NUMBER_OF_ENTRIES ; EntryIndex++ ) {
+
+ //
+ // Get pointers to the volatile data.
+ //
+
+ Packet = (PCONFIGURATION_PACKET)&Configuration->Packet[EntryIndex];
+ Component = &Packet->Component;
+
+ //
+ // If this is not the root entry and the parent field is NULL, zero
+ // entry and skip to next.
+ //
+
+ if ((EntryIndex != 0) && (Packet->Parent == NULL)) {
+ NvChars = (PUCHAR)&NvConfiguration->Packet[EntryIndex];
+ for ( Index = 0 ;
+ Index < sizeof(COMPRESSED_CONFIGURATION_PACKET) ;
+ Index++ ) {
+
+ if (FwROMByteWrite(NvChars++, 0) != ESUCCESS) {
+ FwROMSetARCDataToReadMode();
+ return EIO;
+ }
+
+
+ }
+ continue;
+ }
+
+ //
+ // Determine the parent and store as an index. Note that the index
+ // (Packet->Parent) is 1 based, to reserve the value 0 to mean no
+ // parent.
+ //
+
+ if (EntryIndex != 0) {
+ CompressedPacket.Parent =
+ (UCHAR)(Packet->Parent - &Configuration->Packet[0]) + 1;
+ } else {
+ CompressedPacket.Parent = 0;
+ }
+
+
+ //
+ // Fill in the rest of the fields. Version and ConfigurationDataLength
+ // will never be larger than USHORTS.
+ //
+
+ CompressedPacket.Class = (UCHAR)Component->Class;
+ CompressedPacket.Type = (UCHAR)Component->Type;
+ CompressedPacket.Version = (UCHAR)Component->Version;
+ CompressedPacket.Revision = (UCHAR)Component->Revision;
+ CompressedPacket.Key = Component->Key;
+ CompressedPacket.ConfigurationDataLength =
+ (USHORT)Component->ConfigurationDataLength;
+ CompressedPacket.ConfigurationData = 0;
+
+
+ //
+ // Make sure the top bit of the flag field is zero unless it is set
+ // to be eisa below.
+ //
+
+ CompressedPacket.Flags = *(PUCHAR)(&Component->Flags) & 0x7f;
+
+ //
+ // If the component has an identifier string, copy it to NVRAM,
+ // otherwise set the index to indicate no identifier.
+ //
+
+ if (Component->IdentifierLength != 0) {
+ CompressedPacket.Identifier = NvIdentifierIndex;
+ for ( Index = 0 ; Index < Component->IdentifierLength ; Index++ ) {
+
+ if (FwROMByteWrite(&NvConfiguration->Identifier[NvIdentifierIndex++],
+ Component->Identifier[Index]) !=
+ ESUCCESS) {
+ FwROMSetARCDataToReadMode();
+ return EIO;
+ }
+
+ }
+ } else {
+ CompressedPacket.Identifier = NO_CONFIGURATION_IDENTIFIER;
+ }
+
+ //
+ // If the component has configuration data, copy it to NVRAM.
+ //
+
+ if (Component->ConfigurationDataLength != 0) {
+
+ //
+ // If the parent component is the eisa bus, copy until the end
+ // of the compressed data.
+ //
+
+ if (Packet->Parent->Component.Type == EisaAdapter) {
+ CompressedPacket.ConfigurationData = NvEisaDataIndex;
+ Data = (PUCHAR)Packet->ConfigurationData;
+ for ( Index = 0 ; TRUE ; Index++ ) {
+
+ if (FwROMByteWrite(&NvConfiguration->EisaData[NvEisaDataIndex++],
+ *Data++) != ESUCCESS) {
+ FwROMSetARCDataToReadMode();
+ return EIO;
+ }
+
+ //
+ // If we have written at least two bytes and the last two
+ // bytes were zero we are at the end.
+ //
+
+ if ((Index > 1) && (!*(Data - 1) && !*(Data - 2))) {
+ break;
+ }
+ }
+
+ //
+ // Set a flag to make it easier to determine that this is an
+ // Eisa component.
+ //
+
+ CompressedPacket.Flags |= 0x80;
+
+ } else {
+ CompressedPacket.ConfigurationData = NvDataIndex;
+ Data = (PUCHAR)Packet->ConfigurationData;
+ for ( Index = 0 ; Index < Component->ConfigurationDataLength ; Index++ ) {
+
+ if (FwROMByteWrite(&NvConfiguration->Data[NvDataIndex++],
+ *Data++) != ESUCCESS) {
+ FwROMSetARCDataToReadMode();
+ return EIO;
+ }
+
+ }
+ }
+ }
+
+ //
+ // Write compressed packet to NVRAM.
+ //
+
+ CompressedChars = (PUCHAR)&CompressedPacket;
+ NvChars = (PUCHAR)&NvConfiguration->Packet[EntryIndex];
+
+ for ( Index = 0 ;
+ Index < sizeof(COMPRESSED_CONFIGURATION_PACKET) ;
+ Index++ ) {
+ if (FwROMByteWrite(NvChars++, *CompressedChars++) != ESUCCESS) {
+ FwROMSetARCDataToReadMode();
+ return EIO;
+ }
+
+ }
+ }
+
+
+ //
+ // Zero the rest of the identifier and configuration data areas.
+ //
+
+ for ( Index = NvIdentifierIndex ; Index < LENGTH_OF_IDENTIFIER ; Index++ ) {
+ if (FwROMByteWrite(&NvConfiguration->Identifier[Index], 0) != ESUCCESS) {
+ FwROMSetARCDataToReadMode();
+ return EIO;
+ }
+ }
+
+
+ for ( Index = NvDataIndex ; Index < LENGTH_OF_DATA ; Index++ ) {
+ if (FwROMByteWrite(&NvConfiguration->Data[Index] ,0) != ESUCCESS) {
+ FwROMSetARCDataToReadMode();
+ return EIO;
+ }
+ }
+
+ for ( Index = NvEisaDataIndex ; Index < LENGTH_OF_EISA_DATA ; Index++ ) {
+ if (FwROMByteWrite(&NvConfiguration->EisaData[Index] ,0) != ESUCCESS) {
+ FwROMSetARCDataToReadMode();
+ return EIO;
+ }
+ }
+
+
+ //
+ // Write configuration data checksum.
+ //
+
+
+#ifdef ALPHA
+
+ if ((FwConfigurationSetChecksum() != ESUCCESS)
+ ||
+ (FwEnvironmentStore() != ESUCCESS)
+ ) {
+ FwROMSetARCDataToReadMode();
+ return EIO;
+ }
+
+
+ FwROMSetARCDataToReadMode();
+
+#else
+ FwConfigurationSetChecksum();
+#endif
+
+ //
+ // Restore configuration information out of NVRAM. This acts to compress
+ // the identifier and configuration data areas if any deletes have been
+ // performed.
+ //
+
+ return FwRestoreConfiguration();
+
+
+#else // !defined(FAILSAFE_BOOTER)
+
+ //
+ // The FailSafe Booter needs this function defined for a call in
+ // the scsidisk.c module.
+ //
+
+ return ESUCCESS;
+
+#endif // !defined(FAILSAFE_BOOTER)
+
+}
+
+
+#if !defined(FAILSAFE_BOOTER)
+ARC_STATUS
+FwRestoreConfiguration (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine restores all of the configuration entries from NVRAM,
+ including the associated identifier strings and configuration data.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns ESUCCESS if the restore completed successfully, otherwise one of
+ the following error codes is returned.
+
+ EIO Invalid NVRAM checksum.
+
+--*/
+
+{
+ ULONG EntryIndex;
+ ULONG Index;
+ PCONFIGURATION_PACKET Packet;
+ PCONFIGURATION_COMPONENT Component;
+ PNV_CONFIGURATION NvConfiguration;
+ COMPRESSED_CONFIGURATION_PACKET CompressedPacket;
+ USHORT NvIdentifierIndex;
+ USHORT NvDataIndex;
+ USHORT NvEisaDataIndex;
+ PUCHAR CompressedChars, NvChars;
+ PCONFIGURATION_PACKET SearchPacket;
+ ULONG Long;
+
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
+ NvIdentifierIndex = 0;
+ NvDataIndex = 0;
+ NvEisaDataIndex = 0;
+ IdentifierIndex = 0;
+ DataIndex = 0;
+ EisaDataIndex = 0;
+
+
+ //
+ // Check the checksum, return error if invalid.
+ //
+
+ if (FwConfigurationCheckChecksum() != ESUCCESS) {
+ return EIO;
+ }
+
+ //
+ // Clear the configuration area.
+ //
+
+ RtlZeroMemory(Configuration, sizeof(CONFIGURATION));
+
+ //
+ // Read each non-volatile compressed packet into a volatile packet,
+ // including the identifier string and the configuration data.
+ //
+
+ for ( EntryIndex = 0 ; EntryIndex < NUMBER_OF_ENTRIES ; EntryIndex++ ) {
+
+ //
+ // Read compressed packet from NVRAM.
+ //
+
+ CompressedChars = (PUCHAR)&CompressedPacket;
+ NvChars = (PUCHAR)&NvConfiguration->Packet[EntryIndex];
+
+ for ( Index = 0 ;
+ Index < sizeof(COMPRESSED_CONFIGURATION_PACKET) ;
+ Index++ ) {
+ *CompressedChars++ = HalpReadNVByte( NvChars++ );
+ }
+
+
+ //
+ // If this is not the root entry and the parent field is NULL,
+ // go to the next.
+ //
+
+ if ((EntryIndex != 0) && (CompressedPacket.Parent == 0)) {
+ continue;
+ }
+
+ //
+ // Get pointers to the volatile area.
+ //
+
+ Packet = (PCONFIGURATION_PACKET)&Configuration->Packet[EntryIndex];
+ Component = &Packet->Component;
+
+
+ //
+ // If not the root entry and the parent field is within range, fill
+ // in parent field (note that the parent index
+ // is 1 based, subtract 1 to get correct index). If the parents child
+ // pointer is NULL, fill in with the current entry, otherwise follow
+ // the links and add the current entry as the last peer.
+ //
+
+ if ((EntryIndex != 0) && (CompressedPacket.Parent <= NUMBER_OF_ENTRIES)) {
+ Packet->Parent = &Configuration->Packet[CompressedPacket.Parent - 1];
+ SearchPacket = Packet->Parent;
+
+ if (SearchPacket->Child == NULL) {
+ SearchPacket->Child = Packet;
+ } else {
+ SearchPacket = SearchPacket->Child;
+ while ( SearchPacket->Peer != NULL ) {
+ SearchPacket = SearchPacket->Peer;
+ }
+ SearchPacket->Peer = Packet;
+ }
+ } else {
+ Packet->Parent = NULL;
+ }
+
+
+ //
+ // NULL current packets child and peer pointers.
+ //
+
+ Packet->Child = NULL;
+ Packet->Peer = NULL;
+
+
+ //
+ // Fill in the rest of the fields.
+ //
+
+ Component->Class = (CONFIGURATION_CLASS)CompressedPacket.Class;
+ Component->Type = (CONFIGURATION_TYPE)CompressedPacket.Type;
+ Component->Flags.Failed = (CompressedPacket.Flags & 0x01) ? 1 : 0;
+ Component->Flags.ReadOnly = (CompressedPacket.Flags & 0x02) ? 1 : 0;
+ Component->Flags.Removable = (CompressedPacket.Flags & 0x04) ? 1 : 0;
+ Component->Flags.ConsoleIn = (CompressedPacket.Flags & 0x08) ? 1 : 0;
+ Component->Flags.ConsoleOut = (CompressedPacket.Flags & 0x10) ? 1 : 0;
+ Component->Flags.Input = (CompressedPacket.Flags & 0x20) ? 1 : 0;
+ Component->Flags.Output = (CompressedPacket.Flags & 0x40) ? 1 : 0;
+ Component->Version = (USHORT)CompressedPacket.Version;
+ Component->Revision = (USHORT)CompressedPacket.Revision;
+ Component->Key = CompressedPacket.Key;
+ Component->AffinityMask = 0xffffffff;
+ Component->ConfigurationDataLength =
+ (ULONG)CompressedPacket.ConfigurationDataLength;
+
+ //
+ // If the component has an identifier string, copy it to memory.
+ //
+
+ Index = 0;
+
+ if (CompressedPacket.Identifier != NO_CONFIGURATION_IDENTIFIER) {
+ Component->Identifier = &Configuration->Identifier[IdentifierIndex];
+ do {
+ Configuration->Identifier[IdentifierIndex++] =
+ HalpReadNVByte(
+ &NvConfiguration->Identifier[NvIdentifierIndex] );
+ Index++;
+ } while ( HalpReadNVByte(&NvConfiguration->Identifier[NvIdentifierIndex++] ) );
+ }
+
+ //
+ // Set identifier length field.
+ //
+
+ Component->IdentifierLength = Index;
+
+ //
+ // If the component has configuration data, copy it to memory.
+ //
+
+ if (Component->ConfigurationDataLength != 0) {
+
+ //
+ // If the eisa flag is set, only copy the compressed data.
+ //
+
+ if (CompressedPacket.Flags & 0x80) {
+ Packet->ConfigurationData = &Configuration->EisaData[EisaDataIndex];
+ for ( Index = 0 ; TRUE ; Index++ ) {
+ Configuration->EisaData[EisaDataIndex++] =
+ HalpReadNVByte( &NvConfiguration->EisaData[NvEisaDataIndex++] );
+
+ //
+ // If at least two bytes have been written and the last
+ // two bytes are zero, we are at the end.
+ //
+
+ if ((Index > 1) &&
+ (!Configuration->EisaData[EisaDataIndex - 1] &
+ !Configuration->EisaData[EisaDataIndex - 2])) {
+ break;
+ }
+ }
+ } else {
+ Packet->ConfigurationData = &Configuration->Data[DataIndex];
+ for ( Index = 0 ; Index < Component->ConfigurationDataLength ; Index++ ) {
+ Configuration->Data[DataIndex++] =
+ HalpReadNVByte( &NvConfiguration->Data[NvDataIndex++] );
+ }
+ }
+ }
+
+ }
+
+
+ return(ESUCCESS);
+}
+
+#endif // !defined(FAILSAFE_BOOTER)
+
+#if !defined(FAILSAFE_BOOTER)
+ARC_STATUS
+FwConfigurationCheckChecksum (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine checks the configuration checksum.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the checksum is good, ESUCCESS is returned, otherwise EIO is returned.
+
+--*/
+
+{
+ PUCHAR NvChars;
+ PNV_CONFIGURATION NvConfiguration;
+ ULONG Index;
+ ULONG Checksum1, Checksum2;
+
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
+
+ //
+ // Form checksum from NVRAM data.
+ //
+
+ Checksum1 = 0;
+ NvChars = (PUCHAR)NVRAM_CONFIGURATION;
+
+ for ( Index = 0 ;
+ Index < sizeof(COMPRESSED_CONFIGURATION_PACKET) * NUMBER_OF_ENTRIES +
+ LENGTH_OF_IDENTIFIER + LENGTH_OF_DATA;
+ Index++ ) {
+ Checksum1 += HalpReadNVByte( NvChars++ );
+ }
+
+ //
+ // Reconstitute checksum and return error if no compare.
+ //
+
+ Checksum2 = (ULONG)HalpReadNVByte( &NvConfiguration->Checksum1[0] ) |
+ (ULONG)HalpReadNVByte( &NvConfiguration->Checksum1[1] ) << 8 |
+ (ULONG)HalpReadNVByte( &NvConfiguration->Checksum1[2] ) << 16 |
+ (ULONG)HalpReadNVByte( &NvConfiguration->Checksum1[3] ) << 24 ;
+
+ if (Checksum1 != Checksum2) {
+ return EIO;
+ }
+
+ //
+ // Repeat for the eisa data area.
+ //
+
+ Checksum1 = 0;
+ NvChars = (PUCHAR)NvConfiguration->EisaData;
+
+ for ( Index = 0 ;
+ Index < LENGTH_OF_EISA_DATA;
+ Index++ ) {
+ Checksum1 += HalpReadNVByte( NvChars++ );
+ }
+
+ //
+ // Reconstitute checksum and return error if no compare.
+ //
+
+ Checksum2 = (ULONG)HalpReadNVByte( &NvConfiguration->Checksum3[0] ) |
+ (ULONG)HalpReadNVByte( &NvConfiguration->Checksum3[1] ) << 8 |
+ (ULONG)HalpReadNVByte( &NvConfiguration->Checksum3[2] ) << 16 |
+ (ULONG)HalpReadNVByte( &NvConfiguration->Checksum3[3] ) << 24 ;
+
+ if (Checksum1 != Checksum2) {
+ return EIO;
+ }
+
+ return(ESUCCESS);
+}
+
+#endif // !defined(FAILSAFE_BOOTER)
+
+#if !defined(FAILSAFE_BOOTER)
+ARC_STATUS
+FwConfigurationSetChecksum (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the configuration checksum.
+
+ This has been coded for Alpha/Jensen. It assumes that the
+ block containing the checksum has already been erased and
+ written to, and that the status of these previous operations
+ has already been checked.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ ESUCCESS if the checksum was written OK.
+ EIO otherwise.
+
+--*/
+
+{
+ PUCHAR NvChars;
+ PNV_CONFIGURATION NvConfiguration;
+ ULONG Index;
+ ULONG Checksum1;
+
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
+
+ FwROMSetARCDataToReadMode();
+
+ //
+ // Form checksum from NVRAM data.
+ //
+
+ Checksum1 = 0;
+ NvChars = (PUCHAR)NvConfiguration;
+
+ for ( Index = 0 ;
+ Index < sizeof(COMPRESSED_CONFIGURATION_PACKET) * NUMBER_OF_ENTRIES +
+ LENGTH_OF_IDENTIFIER + LENGTH_OF_DATA;
+ Index++ ) {
+ Checksum1 += HalpReadNVByte( NvChars++ );
+ }
+
+ //
+ // Set checksum.
+ //
+
+ FwROMResetStatus(&NvConfiguration->Checksum1[0]);
+
+ if ((FwROMByteWrite(&NvConfiguration->Checksum1[0],
+ (UCHAR)(Checksum1 & 0xFF)) != ESUCCESS) ||
+ (FwROMByteWrite(&NvConfiguration->Checksum1[1],
+ (UCHAR)((Checksum1 >> 8) & 0xFF)) != ESUCCESS) ||
+ (FwROMByteWrite(&NvConfiguration->Checksum1[2],
+ (UCHAR)((Checksum1 >> 16) & 0xFF)) != ESUCCESS) ||
+ (FwROMByteWrite(&NvConfiguration->Checksum1[3],
+ (UCHAR)(Checksum1 >> 24)) != ESUCCESS)) {
+ return EIO;
+ }
+
+ //
+ // Repeat for the eisa data area.
+ //
+
+ Checksum1 = 0;
+ NvChars = (PUCHAR)NvConfiguration->EisaData;
+
+ for ( Index = 0 ;
+ Index < LENGTH_OF_EISA_DATA;
+ Index++ ) {
+ Checksum1 += HalpReadNVByte( NvChars++ );
+ }
+
+ //
+ // Set checksum.
+ //
+
+ FwROMResetStatus(&NvConfiguration->Checksum3[0]);
+
+ if ((FwROMByteWrite(&NvConfiguration->Checksum3[0],
+ (UCHAR)(Checksum1 & 0xFF)) != ESUCCESS) ||
+ (FwROMByteWrite(&NvConfiguration->Checksum3[1],
+ (UCHAR)((Checksum1 >> 8) & 0xFF)) != ESUCCESS) ||
+ (FwROMByteWrite(&NvConfiguration->Checksum3[2],
+ (UCHAR)((Checksum1 >> 16) & 0xFF)) != ESUCCESS) ||
+ (FwROMByteWrite(&NvConfiguration->Checksum3[3],
+ (UCHAR)(Checksum1 >> 24)) != ESUCCESS)) {
+ return EIO;
+ } else {
+ return ESUCCESS;
+ }
+
+}
+#endif // !defined(FAILSAFE_BOOTER)
+
+#if !defined(FAILSAFE_BOOTER)
+ULONG
+FwZeroCompressLength (
+ IN ULONG DataLength,
+ IN PVOID ConfigurationData
+ )
+
+/*++
+
+Routine Description:
+
+ This routine returns the compressed length of a configuration data sample.
+
+Arguments:
+
+ DataLength - Supplies the uncompressed length of the data.
+
+ ConfigurationData - Supplies a pointer to the uncompressed configuration data.
+
+Return Value:
+
+ Returns the compressed length of the configuration data.
+
+--*/
+
+{
+ ULONG Index;
+ ULONG CompressedLength;
+ ULONG Zero;
+ PUCHAR In;
+
+ CompressedLength = 2;
+ Zero = 0;
+ In = ConfigurationData;
+
+ for (Index = 0; Index < DataLength ; Index++ ) {
+ if (*In++) {
+ CompressedLength++;
+ Zero = 0;
+ } else {
+ if (Zero++) {
+ if (Zero == 0x100) {
+ Zero = 1;
+ CompressedLength += 2;
+ }
+ } else {
+ CompressedLength += 2;
+ }
+ }
+ }
+ return(CompressedLength);
+}
+
+#endif // !defined(FAILSAFE_BOOTER)
+
+#if !defined(FAILSAFE_BOOTER)
+ULONG
+FwZeroCompress (
+ IN ULONG DataLength,
+ IN PVOID ConfigurationData,
+ OUT PVOID OutputBuffer
+ )
+
+/*++
+
+Routine Description:
+
+ This routine compresses configuration data.
+
+Arguments:
+
+ DataLength - Supplies the uncompressed length of the data.
+
+ ConfigurationData - Supplies a pointer to the uncompressed configuration data.
+
+ OutputBuffer - Supplies a pointer to the buffer to receive the compressed data.
+
+Return Value:
+
+ Returns the compressed length of the configuration data.
+
+--*/
+
+{
+ ULONG Index;
+ ULONG CompressedLength;
+ ULONG Zero;
+ PUCHAR In, Out;
+
+ In = (PUCHAR)ConfigurationData;
+ Out = (PUCHAR)OutputBuffer;
+ CompressedLength = 2;
+ Zero = 0;
+
+ for (Index = 0; Index < DataLength ; Index++ ) {
+ if (*In) {
+ if (Zero) {
+ Out++;
+ Zero = 0;
+ }
+ *Out++ = *In;
+ CompressedLength++;
+ } else {
+ if (Zero++) {
+ if (Zero == 0x100) {
+ *Out++ = 0xFF;
+ *Out++ = 0;
+ *Out = 1;
+ Zero = 1;
+ CompressedLength += 2;
+ } else {
+ *Out += 1;
+ }
+ } else {
+ *Out++ = 0;
+ *Out = 1;
+ CompressedLength += 2;
+ }
+ }
+ In++;
+ }
+
+ if (Zero) {
+ Out++;
+ }
+
+ *Out++ = 0;
+ *Out = 0;
+
+ return(CompressedLength);
+}
+
+#endif // !defined(FAILSAFE_BOOTER)
+
+#if !defined(FAILSAFE_BOOTER)
+VOID
+FwZeroDecompress (
+ IN PVOID InBuffer,
+ IN ULONG Index,
+ OUT PVOID ConfigurationData,
+ IN ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine decompresses configuration data.
+
+Arguments:
+
+ InBuffer - Supplies a pointer to the compressed configuration data.
+
+ Index - Supplies the index into the uncompressed data to start returning.
+
+ ConfigurationData - Supplies a pointer to the output buffer.
+
+ Length - Supplies the length of data to uncompress.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG DecompressedLength;
+ ULONG Zero;
+ PUCHAR In, Out;
+ UCHAR OutChar;
+
+ if (InBuffer == NULL) {
+ return;
+ }
+
+ In = (PUCHAR)InBuffer;
+ Out = (PUCHAR)ConfigurationData;
+ DecompressedLength = 0;
+ Zero = 0;
+
+ while (DecompressedLength++ < Index + Length) {
+
+ if (Zero) {
+ Zero--;
+ } else if (*In) {
+ OutChar = *In++;
+ } else {
+ OutChar = 0;
+ Zero = *(++In) - 1;
+ In++;
+ }
+
+ if (DecompressedLength > Index) {
+ *Out++ = OutChar;
+ }
+
+ }
+
+}
+
+#endif // !defined(FAILSAFE_BOOTER)
diff --git a/private/ntos/fw/alpha/jxdisp.c b/private/ntos/fw/alpha/jxdisp.c
new file mode 100644
index 000000000..2993224a6
--- /dev/null
+++ b/private/ntos/fw/alpha/jxdisp.c
@@ -0,0 +1,3460 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ jxdisp.c
+
+Abstract:
+
+ This module implements the video boot driver for the Jensen system.
+
+Author:
+
+ David M. Robinson (davidro) 24-Jul-1991
+
+Environment:
+
+ Kernel mode.
+
+
+Revision History:
+
+
+ 30-April-1992 John DeRosa [DEC]
+ Added Alpha/Jensen modifications.
+
+ 30-March-1993 Bruce Butts [DEC]
+ Added Alpha/Morgan modifications.
+
+--*/
+
+// HEADER_FILE must be defined so that kxalpha.h will not generate
+// assembler pseudo-ops.
+#define HEADER_FILE=1
+
+#include "fwp.h"
+#include "machdef.h"
+#include "jnsnvdeo.h"
+#include "ati.h" // definitions for ati mach board.
+#include "kxalpha.h"
+#include "..\miniport\aha174x\aha174x.h" // for MAXIMUM_EISA_SLOTS definition
+#include "xxstring.h"
+
+
+#ifdef ALPHA_FW_VDB
+
+//
+// For video board debugging
+//
+UCHAR DebugAid[3][150];
+
+VOID
+FwVideoStateDump(
+ IN ULONG Index
+ );
+
+#endif // ALPHA_FW_VDB
+
+#ifdef ALPHA_FW_SERDEB
+
+//
+// Variable that enables printing on the COM1 line.
+//
+extern BOOLEAN SerSnapshot;
+
+#endif // ALPHA_FW_SERDEB
+
+//
+// S3 clock init.
+//
+long calc_clock(long, int);
+
+ULONG
+SerFwPrint (
+ PCHAR Format,
+ ...
+ );
+
+//
+
+ARC_STATUS
+FwInitializeGraphicsCard (
+ OUT PALPHA_VIDEO_TYPE VideoType
+ );
+
+ULONG
+FwDetermineCardType (
+ VOID
+ );
+
+VOID
+FillVideoMemory (
+ IN volatile PUCHAR StartAddress,
+ IN ULONG SizeInBytes,
+ IN ULONG Pattern
+ );
+
+ARC_STATUS
+DisplayClose (
+ IN ULONG FileId
+ );
+
+ARC_STATUS
+DisplayMount (
+ IN PCHAR MountPath,
+ IN MOUNT_OPERATION Operation
+ );
+
+ARC_STATUS
+DisplayOpen (
+ IN PCHAR OpenPath,
+ IN OPEN_MODE OpenMode,
+ IN OUT PULONG FileId
+ );
+
+ARC_STATUS
+DisplayRead (
+ IN ULONG FileId,
+ IN PVOID Buffer,
+ IN ULONG Length,
+ OUT PULONG Count
+ );
+
+ARC_STATUS
+DisplayGetReadStatus (
+ IN ULONG FileId
+ );
+
+ARC_STATUS
+DisplaySeek (
+ IN ULONG FileId,
+ IN PLARGE_INTEGER Offset,
+ IN SEEK_MODE SeekMode
+ );
+
+ARC_STATUS
+DisplayWrite (
+ IN ULONG FileId,
+ IN PVOID Buffer,
+ IN ULONG Length,
+ OUT PULONG Count
+ );
+
+ARC_STATUS
+DisplayGetFileInformation (
+ IN ULONG FileId,
+ OUT PFILE_INFORMATION Finfo
+ );
+
+//
+// Define colors, HI = High Intensity
+//
+// The palette registers are simply 1:1 indirections to the color registers.
+//
+//
+
+#define FW_COLOR_BLACK 0x00
+#define FW_COLOR_RED 0x01
+#define FW_COLOR_GREEN 0x02
+#define FW_COLOR_YELLOW 0x03
+#define FW_COLOR_BLUE 0x04
+#define FW_COLOR_MAGENTA 0x05
+#define FW_COLOR_CYAN 0x06
+#define FW_COLOR_WHITE 0x07
+#define FW_COLOR_HI_BLACK 0x08
+#define FW_COLOR_HI_RED 0x09
+#define FW_COLOR_HI_GREEN 0x0A
+#define FW_COLOR_HI_YELLOW 0x0B
+#define FW_COLOR_HI_BLUE 0x0C
+#define FW_COLOR_HI_MAGENTA 0x0D
+#define FW_COLOR_HI_CYAN 0x0E
+#define FW_COLOR_HI_WHITE 0x0F
+
+#define PALETTE_BLACK 0x00
+#define PALETTE_RED 0x01
+#define PALETTE_GREEN 0x02
+#define PALETTE_YELLOW 0x03
+#define PALETTE_BLUE 0x04
+#define PALETTE_MAGENTA 0x05
+#define PALETTE_CYAN 0x06
+#define PALETTE_WHITE 0x07
+#define PALETTE_HI_BLACK 0x08
+#define PALETTE_HI_RED 0x09
+#define PALETTE_HI_GREEN 0x0a
+#define PALETTE_HI_YELLOW 0x0b
+#define PALETTE_HI_BLUE 0x0c
+#define PALETTE_HI_MAGENTA 0x0d
+#define PALETTE_HI_CYAN 0x0e
+#define PALETTE_HI_WHITE 0x0f
+
+#define COLOR_REGISTER_BLACK_R 0x00
+#define COLOR_REGISTER_BLACK_G 0x00
+#define COLOR_REGISTER_BLACK_B 0x00
+
+#define COLOR_REGISTER_RED_R 0x2A
+#define COLOR_REGISTER_RED_G 0x00
+#define COLOR_REGISTER_RED_B 0x00
+
+#define COLOR_REGISTER_GREEN_R 0x00
+#define COLOR_REGISTER_GREEN_G 0x2A
+#define COLOR_REGISTER_GREEN_B 0x00
+
+#define COLOR_REGISTER_YELLOW_R 0x2a
+#define COLOR_REGISTER_YELLOW_G 0x2a
+#define COLOR_REGISTER_YELLOW_B 0x00
+
+#define COLOR_REGISTER_BLUE_R 0x00
+#define COLOR_REGISTER_BLUE_G 0x00
+#define COLOR_REGISTER_BLUE_B 0x2a
+
+#define COLOR_REGISTER_MAGENTA_R 0x2a
+#define COLOR_REGISTER_MAGENTA_G 0x00
+#define COLOR_REGISTER_MAGENTA_B 0x2a
+
+#define COLOR_REGISTER_CYAN_R 0x00
+#define COLOR_REGISTER_CYAN_G 0x2a
+#define COLOR_REGISTER_CYAN_B 0x2a
+
+#define COLOR_REGISTER_WHITE_R 0x2a
+#define COLOR_REGISTER_WHITE_G 0x2a
+#define COLOR_REGISTER_WHITE_B 0x2a
+
+#define COLOR_REGISTER_HI_BLACK_R 0x00
+#define COLOR_REGISTER_HI_BLACK_G 0x00
+#define COLOR_REGISTER_HI_BLACK_B 0x00
+
+#define COLOR_REGISTER_HI_RED_R 0x3f
+#define COLOR_REGISTER_HI_RED_G 0x00
+#define COLOR_REGISTER_HI_RED_B 0x00
+
+#define COLOR_REGISTER_HI_GREEN_R 0x00
+#define COLOR_REGISTER_HI_GREEN_G 0x3f
+#define COLOR_REGISTER_HI_GREEN_B 0x00
+
+#define COLOR_REGISTER_HI_YELLOW_R 0x3f
+#define COLOR_REGISTER_HI_YELLOW_G 0x3f
+#define COLOR_REGISTER_HI_YELLOW_B 0x00
+
+#define COLOR_REGISTER_HI_BLUE_R 0x00
+#define COLOR_REGISTER_HI_BLUE_G 0x00
+#define COLOR_REGISTER_HI_BLUE_B 0x3f
+
+#define COLOR_REGISTER_HI_MAGENTA_R 0x3f
+#define COLOR_REGISTER_HI_MAGENTA_G 0x00
+#define COLOR_REGISTER_HI_MAGENTA_B 0x3f
+
+#define COLOR_REGISTER_HI_CYAN_R 0x00
+#define COLOR_REGISTER_HI_CYAN_G 0x3f
+#define COLOR_REGISTER_HI_CYAN_B 0x3f
+
+#define COLOR_REGISTER_HI_WHITE_R 0x3f
+#define COLOR_REGISTER_HI_WHITE_G 0x3f
+#define COLOR_REGISTER_HI_WHITE_B 0x3f
+
+
+
+//
+// Define virtual address of the video memory and control registers.
+//
+
+#define VIDEO_MEMORY ( (volatile PUCHAR)VIDEO_MEMORY_VIRTUAL_BASE )
+#define VIDEO_CONTROL_READ ( (volatile PVGA_READ_REGISTERS)VIDEO_CONTROL_VIRTUAL_BASE )
+#define VIDEO_CONTROL_WRITE ( (volatile PVGA_WRITE_REGISTERS)VIDEO_CONTROL_VIRTUAL_BASE )
+
+
+//
+// Graphics cards are initialized though a video initialization table.
+// The initialization function starts at the beginning of the table
+// and interprets each entry, until the end of the table. Each entry describes
+// one operation (an I/O space access or a function to be performed).
+//
+// A simplifying assumption is that NT/Alpha will boot using VGA mode graphics.
+// Hence, most of the initialization work should be identical across all
+// bootable cards.
+//
+// Fields in each entry:
+//
+// DoIf - Perform the operation in this entry only if the card is one of the
+// types in this mask field. One bit per card.
+//
+// MB - TRUE = Execute a Memory Barrier (MB) instruction after this entry.
+//
+// Operation - Indicates the operation to be performed. This is an
+// I/O space read or write, a special function to be called, etc.
+// Note: The results of I/O space reads are discarded.
+//
+// Size - The size of the operation, if needed: UCHAR, USHORT, or ULONG.
+//
+// Address - The address for the operation, if needed.
+//
+// WriteValue - The constant value to be written on an I/O space write.
+//
+//
+// The cards supported are:
+//
+// - Paradise board with a Western Digital 90C11 chipset. SVGA,
+// non-accelerated. ISA card.
+//
+// - Compaq QVision-family boards. SVGA, accelerated, EISA card. Compaq
+// chipset is a clone of a member of the WD90Cxx family. Specific boards
+// supported are the QVision 1024/E and the Orion 1280/E.
+//
+// - Cardinal board with S3 924 chip (Cardinal name is VGA900, DEC name is
+// PCXAG-AG). SVGA, ISA card.
+//
+// - Number Nine GXE with an S3 928 chip.
+//
+// Cards specifically not supported:
+//
+// - ATI Mach-32 or Mach-8 board. Tested unit was a Mach-32. The screen
+// remained blank; this board needs debugging.
+//
+
+//
+// Define Video Initialization Table field types
+//
+
+//
+// Encodings for the DoIf field.
+//
+// These constants define each of the Alpha/Jensen supported video cards.
+// For code compaction, only a byte is used. If the DoIf field is widened,
+// widen AllCards too.
+//
+// HACK: There are parallel definitions in fw\alpha\fwp.h.
+//
+
+#define Paradise_WD90C11 0x1
+#define Compaq_QVision 0x2
+#define Cardinal_S3_924 0x4
+#define S3_928 0x8
+#define ATI_Mach 0x10
+#define AllCards 0xff
+
+
+//
+// Encodings for the Operation field.
+//
+
+typedef enum _VIT_OPERATION {
+ None,
+ Read,
+ Write,
+ LoadFonts,
+ InitializeNumber9Clocks,
+ InitializeATIMachDAC,
+ End_Of_Initialization // Reserved for last table entry.
+} VIT_OPERATION, *PVIT_OPERATION;
+
+
+//
+// Encodings for the Size field.
+//
+
+typedef enum _VIT_SIZE {
+ UChar,
+ UShort,
+ ULong
+} VIT_SIZE, *PVIT_SIZE;
+
+
+
+//
+// Define the Video Initialization Table type. 12 bytes / entry.
+//
+
+typedef struct _VIDEO_INITIALIZATION_TABLE {
+ UCHAR DoIf;
+ BOOLEAN MB;
+ UCHAR Operation;
+ UCHAR Size;
+ PUCHAR Address;
+ ULONG WriteValue;
+} VIDEO_INITIALIZATION_TABLE, *PVIDEO_INITIALIZATION_TABLE;
+
+
+
+//
+// Define the macros for building the video initialization table.
+// As a simplification, every macro automatically sets the MB bit.
+//
+
+// Do an operation with no arguments.
+#define _VIT_Function(FunctionToCall) \
+ { AllCards, TRUE, FunctionToCall, 0, NULL, 0 }
+
+// Do an operation with no arguments, only for certain cards.
+#define _VIT_FunctionIf(Mask, FunctionToCall) \
+ { Mask, TRUE, FunctionToCall, 0, NULL, 0 }
+
+// Do a read operation.
+#define _VIT_Read(Size, Address) \
+ { AllCards, TRUE, Read, Size, (PUCHAR)Address, 0 }
+
+// Do a write operation.
+#define _VIT_Write(Size, Address, Value) \
+ { AllCards, TRUE, Write, Size, (PUCHAR)Address, Value }
+
+// Do a read operation only for certain cards.
+#define _VIT_ReadIf(Mask, Size, Address) \
+ { Mask, TRUE, Read, Size, (PUCHAR)Address, 0 }
+
+// Do a write operation only for certain cards.
+#define _VIT_WriteIf(Mask, Size, Address, Value) \
+ { Mask, TRUE, Write, Size, (PUCHAR)Address, Value }
+
+//
+// The Video Initialization Table
+//
+
+// This table initializes a VGA card to 80 * 25, 16-color alphanumeric
+// mode equivalent to a BIOS mode 7+.
+// The display resolution is set at 720 * 400 pixels, giving a 9 * 16
+// pixel character matrix, for 8 * 16 character fonts. The display's video
+// bandwidth and horizontal scan rates are 28.322 MHz and 31.50 KHz respect-
+// ively for this chosen resolution, giving 900 dots / line. ( eg., for a 9-
+// pixel matrix width, this gives a maximum horizontal total of 100 ).
+
+VIDEO_INITIALIZATION_TABLE VideoInitializationTable[] = {
+
+ //
+ // Awaken the boards that need it.
+ //
+
+ _VIT_WriteIf((Paradise_WD90C11 | Compaq_QVision | ATI_Mach),
+ UChar, EisaIOQva(0x46e8), 0x10),
+ _VIT_WriteIf((Cardinal_S3_924 | S3_928),
+ UChar, EisaIOQva(0x46e8), 0x30),
+ _VIT_Write(UChar, EisaIOQva(0x0102), 0x01),
+ _VIT_Write(UChar, EisaIOQva(0x46e8), 0x08),
+
+
+#if 0
+
+ //
+ // ATI Mach: set extended register address and index. Base = 1ce,
+ // offset = 0.
+ //
+ _VIT_WriteIf(ATI_Mach,
+ UChar, &VIDEO_CONTROL_WRITE->graphics_address, 0x50),
+ _VIT_WriteIf(ATI_Mach,
+ UChar, &VIDEO_CONTROL_WRITE->graphics_data, 0xce),
+ _VIT_WriteIf(ATI_Mach,
+ UChar, &VIDEO_CONTROL_WRITE->graphics_address, 0x51),
+ _VIT_WriteIf(ATI_Mach,
+ UChar, &VIDEO_CONTROL_WRITE->graphics_data, 0x01),
+
+
+ //
+ // ATI Mach: initialize the DAC.
+ //
+
+ _VIT_FunctionIf(ATI_Mach, InitializeATIMachDAC),
+
+#endif
+
+ //
+ // 90Cxx and QVision: Unlock the registers
+ //
+
+ // PR5, which unlocks PR 0--4
+ _VIT_WriteIf((Paradise_WD90C11 | Compaq_QVision),
+ UChar, &VIDEO_CONTROL_WRITE->graphics_address, 0x0f),
+ _VIT_WriteIf((Paradise_WD90C11 | Compaq_QVision),
+ UChar, &VIDEO_CONTROL_WRITE->graphics_data, 0x05),
+
+ // PR3, which unlocks some registers
+ _VIT_WriteIf(Paradise_WD90C11,
+ UChar, &VIDEO_CONTROL_WRITE->graphics_address, 0x0d),
+ _VIT_WriteIf(Paradise_WD90C11,
+ UChar, &VIDEO_CONTROL_WRITE->graphics_data, 0x0),
+
+ // Set color mode now, also selecting the 28.322 Mhz clock
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->misc_output, 0x67),
+
+ // PR10, which unlocks PR11 -- PR17
+ _VIT_WriteIf(Paradise_WD90C11,
+ UChar, &VIDEO_CONTROL_WRITE->crtc_address, 0x29),
+ _VIT_WriteIf(Paradise_WD90C11,
+ UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x85),
+
+ // PR15, enable vclk0, vclk1
+ _VIT_WriteIf(Paradise_WD90C11,
+ UChar, &VIDEO_CONTROL_WRITE->crtc_address, 0x2e),
+ _VIT_WriteIf(Paradise_WD90C11,
+ UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x20),
+
+ // PR20, unlock the extended sequencer registers
+ _VIT_WriteIf(Paradise_WD90C11,
+ UChar, &VIDEO_CONTROL_WRITE->sequencer_address, 0x6),
+ _VIT_WriteIf(Paradise_WD90C11,
+ UChar, &VIDEO_CONTROL_WRITE->sequencer_data, 0x48),
+
+
+ //
+ // S3 911, 924, and 928 based cards: Unlock the registers and reset
+ // extended functionality. The card has already been set to color
+ // mode addressing.
+ //
+
+ // Write S3R8 to unlock the S3 register set
+ _VIT_WriteIf((Cardinal_S3_924 | S3_928),
+ UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_S3924_S3R8),
+ _VIT_WriteIf((Cardinal_S3_924 | S3_928),
+ UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x48),
+ // S3R9: unlock system control registers
+ _VIT_WriteIf((Cardinal_S3_924 | S3_928),
+ UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_S3924_S3R9),
+ _VIT_WriteIf((Cardinal_S3_924 | S3_928),
+ UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0xA0),
+ // S3R1
+ _VIT_WriteIf((Cardinal_S3_924 | S3_928),
+ UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_S3924_S3R1),
+ _VIT_WriteIf((Cardinal_S3_924 | S3_928),
+ UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x00),
+ // S3R2
+ _VIT_WriteIf((Cardinal_S3_924 | S3_928),
+ UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_S3924_S3R2),
+ _VIT_WriteIf((Cardinal_S3_924 | S3_928),
+ UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x0),
+ // S3R3
+ _VIT_WriteIf((Cardinal_S3_924 | S3_928),
+ UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_S3924_S3R3),
+ _VIT_WriteIf((Cardinal_S3_924 | S3_928),
+ UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x0),
+ // S3R4
+ _VIT_WriteIf((Cardinal_S3_924 | S3_928),
+ UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_S3924_S3R4),
+ _VIT_WriteIf((Cardinal_S3_924 | S3_928),
+ UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x0),
+ // S3R5
+ _VIT_WriteIf((Cardinal_S3_924 | S3_928),
+ UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_S3924_S3R5),
+ _VIT_WriteIf((Cardinal_S3_924 | S3_928),
+ UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x0),
+
+
+#if 0 // Only needed if Number9 MClock needs to be reset
+ //
+ // For Number9 / S3928 board: initialize the board clock(s) now.
+ //
+
+ // This code should be rewritten to key off the Number 9 GXE, since
+ // it may not be needed for other S3 928-based graphics adapters
+
+ _VIT_FunctionIf(S3_928, InitializeNumber9Clocks),
+
+ // Reset misc_output for S3_928
+
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->misc_output, 0x67),
+#endif
+
+ //
+ // For Number9 / S3928 board with BT485 DAC - reset DAC to VGA mode.
+ // This sequence also resets the clock doubler, should it have been enabled.
+ // (S3R8 and S3R9 must be unlocked before executing this sequence.)
+ //
+
+ // This code should be rewritten to key off the Number 9 GXE, since
+ // it may not be needed for other S3 928-based graphics adapters
+
+ // Select BT485 extended register 0
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_S3928_CR55),
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x00),
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->pel_address_write_mode, 0x01),
+
+ // Select BT485 extended register 1
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_S3928_CR55),
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x01),
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->pel_mask, 0x80),
+
+ // Select BT485 extened register 2
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_S3928_CR55),
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x02),
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->pel_address_write_mode, 0x00),
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->pel_data, 0x00),
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->pel_mask, 0x00),
+
+ // Select BT485 extended register 1
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_S3928_CR55),
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x01),
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->pel_mask, 0x00),
+
+ // Disable BT485 extened registers
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_S3928_CR55),
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x00),
+
+ // For S3 boards - reset VGA S3 and System Control Register
+
+ // S3RA
+ _VIT_WriteIf((Cardinal_S3_924 | S3_928),
+ UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_S3924_S3RA),
+ _VIT_WriteIf((Cardinal_S3_924 | S3_928),
+ UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x0),
+ // S3RB
+ _VIT_WriteIf((Cardinal_S3_924 | S3_928),
+ UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_S3924_S3RB),
+ _VIT_WriteIf((Cardinal_S3_924 | S3_928),
+ UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x0),
+
+ // S3RC
+ _VIT_WriteIf((Cardinal_S3_924 | S3_928),
+ UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_S3924_S3RC),
+ _VIT_WriteIf((Cardinal_S3_924 | S3_928),
+ UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x14),
+
+ // SC0 - Unlock S3 enhanced registers
+ _VIT_WriteIf((Cardinal_S3_924 | S3_928),
+ UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_S3924_SC0),
+ _VIT_WriteIf((Cardinal_S3_924 | S3_928),
+ UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x01),
+
+ // S3 ADVFUNC-CNTL register: enable VGA functions
+ _VIT_WriteIf((Cardinal_S3_924 | S3_928),
+ UChar, EisaIOQva(0x4ae8), 0x2),
+
+ // SC0 - Lock S3 enhanced registers
+ _VIT_WriteIf((Cardinal_S3_924 | S3_928),
+ UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_S3924_SC0),
+ _VIT_WriteIf((Cardinal_S3_924 | S3_928),
+ UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x0),
+ // SC5
+ _VIT_WriteIf((Cardinal_S3_924 | S3_928),
+ UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_S3924_SC5),
+ _VIT_WriteIf((Cardinal_S3_924 | S3_928),
+ UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x0),
+
+
+
+ //
+ // Main initialization consists of the Misc_Output register (done earlier)
+ // as well as sequencer, graphics controller, and CRTC registers.
+ //
+
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->feature_control, 0x0),
+
+ // Hold Sequencer
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->sequencer_address, VGA_RESET),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->sequencer_data, 0x1),
+ // Select the 9 dot character clock!
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->sequencer_address, VGA_CLOCKING_MODE),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->sequencer_data, 0x0),
+ // Enable planes 0,1 for writing
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->sequencer_address, VGA_MAP_MASK),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->sequencer_data, 0x3),
+ // Select font table location in plane 2
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->sequencer_address, VGA_CHAR_MAP_SELECT),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->sequencer_data, 0x0),
+ // Allow VGA-style memory access (all 256K available)
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->sequencer_address, VGA_MEMORY_MODE),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->sequencer_data, 0x2),
+ // Reset Sequencer
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->sequencer_address, VGA_RESET),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->sequencer_data, 0x3),
+
+
+ //
+ // QVision: set BitBLT enable (unlocks other Triton extended registers.)
+ //
+
+ _VIT_WriteIf(Compaq_QVision,
+ UChar, &VIDEO_CONTROL_WRITE->graphics_address, 0x10),
+ _VIT_WriteIf(Compaq_QVision,
+ UChar, &VIDEO_CONTROL_WRITE->graphics_data, 0x08),
+
+ //
+ // QVision: clear Triton mode
+ //
+
+ _VIT_WriteIf(Compaq_QVision, UChar, EisaIOQva(0x63ca), 0x0),
+
+
+ //
+ // QVision: reset DAC registers
+ //
+
+ _VIT_WriteIf(Compaq_QVision, UChar, EisaIOQva(0x83c6), 0x0), // DAC cmd 0
+ _VIT_WriteIf(Compaq_QVision, UChar, EisaIOQva(0x13c8), 0x0), // DAC cmd 1
+ _VIT_WriteIf(Compaq_QVision, UChar, EisaIOQva(0x13c9), 0x0), // DAC cmd 2
+
+
+ //
+ // QVision: reset overflow registers
+ //
+
+ _VIT_WriteIf(Compaq_QVision,
+ UChar, &VIDEO_CONTROL_WRITE->graphics_address, 0x42),
+ _VIT_WriteIf(Compaq_QVision,
+ UChar, &VIDEO_CONTROL_WRITE->graphics_data, 0x0),
+ _VIT_WriteIf(Compaq_QVision,
+ UChar, &VIDEO_CONTROL_WRITE->graphics_address, 0x51),
+ _VIT_WriteIf(Compaq_QVision,
+ UChar, &VIDEO_CONTROL_WRITE->graphics_data, 0x0),
+
+
+ // Unlock CRTC registers 0 -- 7.
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_VERTICAL_RETRACE_END),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x01),
+
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_HORIZONTAL_TOTAL),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0X5f),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_HORIZONTAL_DISPLAY_END),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x4f),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_START_HORIZONTAL_BLANKING),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x50),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_END_HORIZONTAL_BLANKING),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x82),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_START_HORIZONTAL_RETRACE),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x55),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_END_HORIZONTAL_RETRACE),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x81),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_VERTICAL_TOTAL),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0xbf),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_OVERFLOW),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x1F),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_PRESET_ROW_SCAN),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x0),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_MAXIMUM_SCAN_LINE),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x4f),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_CURSOR_START),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x2e),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_CURSOR_END),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x0F),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_START_ADDRESS_HIGH),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x0),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_START_ADDRESS_LOW),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x0),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_CURSOR_LOCATION_HIGH),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x0),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_CURSOR_LOCATION_LOW),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x0),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_VERTICAL_RETRACE_START),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x9C),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_VERTICAL_RETRACE_END),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x8E),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_VERTICAL_DISPLAY_END),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x8F),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_OFFSET),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x28),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_UNDERLINE_LOCATION),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x1f),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_START_VERTICAL_BLANK),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x96),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_END_VERTICAL_BLANK),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0xB9),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_MODE_CONTROL),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0xa3),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_LINE_COMPARE),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0xff),
+
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_LINE_COMPARE),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0xff),
+
+ // Reset S3 928 System Extension Registers
+
+ // Extended System Control 1
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_S3928_CR50 ),
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x00),
+ // Extended System Control 2
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_S3928_CR51 ),
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x00),
+ // Extended BIOS Flag 1
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_S3928_CR52 ),
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x00),
+ // Extended Memory Control 1
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_S3928_CR53 ),
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x00),
+ // Extended Memory Control 2
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_S3928_CR54 ),
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x00),
+
+ // Extended DAC Control (CR55) - BT485 DAC was reset earlier in table.
+
+ // External Sync Control 1
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_S3928_CR56 ),
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x00),
+ // External Sync Control 2
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_S3928_CR57 ),
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x00),
+ // Linear Addres Window (LAW) Control
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_S3928_CR58 ),
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x00),
+ // Linear Address Window (LAW) Position 0x59-5A
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_S3928_CR59 ),
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x00),
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_S3928_CR5A ),
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x00),
+ // Extended BOIS Flag 2 Register 0x5B
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_S3928_CR5B ),
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x00),
+ // General Ouput Port
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_S3928_CR5C ),
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x00),
+ // Extended Horizontal Overflow 0x5D
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_S3928_CR5D ),
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x00),
+ // Extended Vertical Overflow 0x5E
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_S3928_CR5E ),
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x00),
+ // Bus Grant Termination Position
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_S3928_CR5F ),
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x00),
+ // Magic S3 registers CR60-CR62
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_S3928_CR60 ),
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x07),
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_S3928_CR61 ),
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x00),
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_address, VGA_S3928_CR62 ),
+ _VIT_WriteIf(S3_928, UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x00),
+
+ // Graphics Controller Registers
+
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->graphics_address, VGA_SET_RESET),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->graphics_data, 0x0),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->graphics_address, VGA_ENABLE_SET_RESET),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->graphics_data, 0x0),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->graphics_address, VGA_COLOR_COMPARE),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->graphics_data, 0x0),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->graphics_address, VGA_DATA_ROTATE),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->graphics_data, 0x0),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->graphics_address, VGA_READ_MAP_SELECT),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->graphics_data, 0x0),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->graphics_address, VGA_MODE),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->graphics_data, 0x10),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->graphics_address, VGA_MISCELLANEOUS),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->graphics_data, 0xe),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->graphics_address, VGA_COLOR_DONT_CARE),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->graphics_data, 0x0),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->graphics_address, VGA_BIT_MASK),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->graphics_data, 0xff),
+
+ // WD90C11 PR0A register
+ _VIT_WriteIf((Paradise_WD90C11 | Compaq_QVision),
+ UChar, &VIDEO_CONTROL_WRITE->graphics_address, 0x9),
+ _VIT_WriteIf((Paradise_WD90C11 | Compaq_QVision),
+ UChar, &VIDEO_CONTROL_WRITE->graphics_data, 0x00),
+
+ // WD90C11 PR1, memory size and configuration
+ _VIT_WriteIf((Paradise_WD90C11 | Compaq_QVision),
+ UChar, &VIDEO_CONTROL_WRITE->graphics_address, 0xb),
+ _VIT_WriteIf((Paradise_WD90C11 | Compaq_QVision),
+ UChar, &VIDEO_CONTROL_WRITE->graphics_data, 0x06),
+
+
+ //
+ // WD90C11
+ //
+ //
+ // PR32, magic clock bits
+ _VIT_WriteIf((Paradise_WD90C11 | Compaq_QVision),
+ UChar, &VIDEO_CONTROL_WRITE->sequencer_address, 0x12),
+ _VIT_WriteIf((Paradise_WD90C11 | Compaq_QVision),
+ UChar, &VIDEO_CONTROL_WRITE->sequencer_data, 0x4),
+ // PR2, third clock select line
+ _VIT_WriteIf((Paradise_WD90C11 | Compaq_QVision),
+ UChar, &VIDEO_CONTROL_WRITE->graphics_address, 0x0c),
+ _VIT_WriteIf((Paradise_WD90C11 | Compaq_QVision),
+ UChar, &VIDEO_CONTROL_WRITE->graphics_data, 0x2),
+
+
+
+
+ // Reset attribute address register FF
+ _VIT_Read(UChar, &VIDEO_CONTROL_READ->input_status_1),
+
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, VGA_PALETTE0),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, PALETTE_BLACK),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, VGA_PALETTE1),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, PALETTE_RED),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, VGA_PALETTE2),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, PALETTE_GREEN),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, VGA_PALETTE3),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, PALETTE_YELLOW),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, VGA_PALETTE4),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, PALETTE_BLUE),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, VGA_PALETTE5),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, PALETTE_MAGENTA),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, VGA_PALETTE6),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, PALETTE_CYAN),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, VGA_PALETTE7),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, PALETTE_WHITE),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, VGA_PALETTE8),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, PALETTE_HI_BLACK),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, VGA_PALETTE9),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, PALETTE_HI_RED),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, VGA_PALETTEA),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, PALETTE_HI_GREEN),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, VGA_PALETTEB),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, PALETTE_HI_YELLOW),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, VGA_PALETTEC),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, PALETTE_HI_BLUE),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, VGA_PALETTED),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, PALETTE_HI_MAGENTA),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, VGA_PALETTEE),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, PALETTE_HI_CYAN),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, VGA_PALETTEF),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, PALETTE_HI_WHITE),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, VGA_ATTR_MODE_CONTROL),
+// _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, 0x0),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, 0x4),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, VGA_OVERSCAN),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, 0x0),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, VGA_COLOR_PLANE_ENABLE),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, 0xf),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, VGA_HORIZONTAL_PIXEL_PANNING),
+// _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, 0x0),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, 0x8),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, VGA_COLOR_SELECT),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, 0x0),
+
+ // This is only to flip the PAS mux. Write address only, flipper
+ // left pointing at data.
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->attribute_adddata, VGA_SET_PAS),
+
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_mask, 0xff),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_address_write_mode, 0x0),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_BLACK_R), // reg0
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_BLACK_G),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_BLACK_B),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_RED_R), // reg1
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_RED_G),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_RED_B),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_GREEN_R), // reg2
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_GREEN_G),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_GREEN_B),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_YELLOW_R), // reg3
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_YELLOW_G),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_YELLOW_B),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_BLUE_R), // reg4
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_BLUE_G),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_BLUE_B),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_MAGENTA_R), // reg5
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_MAGENTA_G),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_MAGENTA_B),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_CYAN_R), // reg6
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_CYAN_G),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_CYAN_B),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_WHITE_R), // reg7
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_WHITE_G),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_WHITE_B),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_HI_BLACK_R), // reg8
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_HI_BLACK_G),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_HI_BLACK_B),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_HI_RED_R), // reg9
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_HI_RED_G),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_HI_RED_B),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_HI_GREEN_R), // rega
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_HI_GREEN_G),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_HI_GREEN_B),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_HI_YELLOW_R), // regb
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_HI_YELLOW_G),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_HI_YELLOW_B),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_HI_BLUE_R), // regc
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_HI_BLUE_G),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_HI_BLUE_B),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_HI_MAGENTA_R), // regd
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_HI_MAGENTA_G),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_HI_MAGENTA_B),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_HI_CYAN_R), // rege
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_HI_CYAN_G),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_HI_CYAN_B),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_HI_WHITE_R), // regf
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_HI_WHITE_G),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->pel_data, COLOR_REGISTER_HI_WHITE_B),
+
+ _VIT_WriteIf((Paradise_WD90C11 | Compaq_QVision), UChar, &VIDEO_CONTROL_WRITE->crtc_address, 0x29),
+ _VIT_WriteIf((Paradise_WD90C11 | Compaq_QVision), UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x85),
+ _VIT_WriteIf((Paradise_WD90C11 | Compaq_QVision), UChar, &VIDEO_CONTROL_WRITE->crtc_address, 0x2e),
+ _VIT_WriteIf((Paradise_WD90C11 | Compaq_QVision), UChar, &VIDEO_CONTROL_WRITE->crtc_data, 0x20),
+
+ // Now load the fonts into bit plane 2, then turn on planes 0 and 1.
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->sequencer_address, VGA_MAP_MASK),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->sequencer_data, 0x4),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->sequencer_address, VGA_MEMORY_MODE),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->sequencer_data, 0x6),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->graphics_address, VGA_MODE),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->graphics_data, 0x0),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->graphics_address, VGA_MISCELLANEOUS),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->graphics_data, 0x5),
+
+ _VIT_Function(LoadFonts),
+
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->sequencer_address, VGA_MAP_MASK),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->sequencer_data, 0x3),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->sequencer_address, VGA_MEMORY_MODE),
+// _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->sequencer_data, 0x3),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->sequencer_data, 0x2),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->graphics_address, VGA_MODE),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->graphics_data, 0x10),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->graphics_address, VGA_MISCELLANEOUS),
+ _VIT_Write(UChar, &VIDEO_CONTROL_WRITE->graphics_data, 0xe),
+
+ // This must be the last entry in the table.
+ _VIT_Function(End_Of_Initialization)
+};
+
+//
+// Define and initialize device table.
+//
+
+#ifdef FAILSAFE_BOOTER
+BL_DEVICE_ENTRY_TABLE DisplayEntryTable = {
+ DisplayClose,
+ DisplayMount,
+ DisplayOpen,
+ NULL,
+ DisplayGetReadStatus,
+ DisplaySeek,
+ DisplayWrite,
+ DisplayGetFileInformation,
+ NULL,
+ NULL,
+ NULL
+ };
+
+#else // ndef FAILSAFE_BOOTER
+
+BL_DEVICE_ENTRY_TABLE DisplayEntryTable = {
+ DisplayClose,
+ DisplayMount,
+ DisplayOpen,
+ DisplayRead,
+ DisplayGetReadStatus,
+ DisplaySeek,
+ DisplayWrite,
+ DisplayGetFileInformation,
+ NULL,
+ NULL,
+ NULL
+ };
+
+#endif
+
+//
+// Static data.
+//
+
+ARC_DISPLAY_STATUS DisplayStatus;
+BOOLEAN ControlSequence;
+BOOLEAN EscapeSequence;
+BOOLEAN FontSelection;
+ULONG PCount;
+LONG FwColumn;
+LONG FwRow;
+BOOLEAN FwHighIntensity;
+BOOLEAN FwUnderscored;
+BOOLEAN FwReverseVideo;
+ULONG FwForegroundColor;
+ULONG FwBackgroundColor;
+ULONG DisplayWidth;
+ULONG DisplayHeight;
+ULONG MaxRow;
+ULONG MaxColumn;
+
+
+#define CONTROL_SEQUENCE_MAX_PARAMETER 10
+ULONG Parameter[CONTROL_SEQUENCE_MAX_PARAMETER];
+
+
+#if 0
+
+//
+// Originally, this table was used to translate a line-drawing character
+// to a Unicode offset, and then the low-level function (FwOutputCharacter)
+// was passed a line-drawing flag that made it use the line fonts.
+//
+// This module loads all the fonts into VGA bit plane 2, including the
+// line drawing fonts. So, no special treatment is needed, and this array
+// is unnecessary.
+//
+
+UCHAR LdAsciiToUnicode[40] = {0x02, 0x24, 0x61, 0x62, 0x56, 0x55, 0x63, 0x51,
+ 0x57, 0x5d, 0x5c, 0x5b, 0x10, 0x14, 0x34, 0x2c,
+ 0x1c, 0x00, 0x3c, 0x5e, 0x5f, 0x5a, 0x54, 0x69,
+ 0x66, 0x60, 0x50, 0x6c, 0x67, 0x68, 0x64, 0x65,
+ 0x59, 0x58, 0x52, 0x53, 0x6b, 0x6a, 0x18, 0x0c };
+#endif
+
+//
+// Declare externally defined data.
+//
+
+// Fonts
+extern UCHAR VGA8x16Chars[];
+extern UCHAR VGA8x16Undef[];
+#ifndef FAILSAFE_BOOTER
+extern UCHAR VGA8x16LineDrawing[];
+#endif
+
+//
+// Define routine prototypes.
+//
+
+VOID
+FwDisplayCharacter(
+ IN UCHAR Character,
+ IN BOOLEAN LineDrawCharacter
+ );
+
+VOID
+FwScrollDisplay(
+ VOID
+ );
+
+
+
+ARC_STATUS
+DisplayGetFileInformation (
+ IN ULONG FileId,
+ OUT PFILE_INFORMATION Finfo
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns EINVAL as no FileInformation can be
+ returned for the Display driver.
+
+Arguments:
+
+ The arguments are not used.
+
+Return Value:
+
+ EINVAL is returned
+
+--*/
+
+{
+ return EINVAL;
+}
+
+
+ARC_STATUS
+DisplayClose (
+ IN ULONG FileId
+ )
+
+/*++
+
+Routine Description:
+
+ This function closes the file table entry specified by the file id.
+
+Arguments:
+
+ FileId - Supplies the file table index.
+
+Return Value:
+
+ ESUCCESS is returned
+
+--*/
+
+{
+
+ BlFileTable[FileId].Flags.Open = 0;
+ return ESUCCESS;
+}
+
+ARC_STATUS
+DisplayMount (
+ IN PCHAR MountPath,
+ IN MOUNT_OPERATION Operation
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ return EINVAL;
+}
+
+ARC_STATUS
+DisplayOpen (
+ IN PCHAR OpenPath,
+ IN OPEN_MODE OpenMode,
+ IN OUT PULONG FileId
+ )
+/*++
+
+Routine Description:
+
+ This is the open routine for the display device.
+
+Arguments:
+
+ OpenPath - Supplies the pathname of the device to open.
+
+ OpenMode - Supplies the mode (read only, write only, or read write).
+
+ FileId - Supplies a free file identifier to use. If the device is already
+ open this parameter can be used to return the file identifier
+ already in use.
+
+Return Value:
+
+ If the open was successful, ESUCCESS is returned, otherwise an error code
+ is returned.
+
+--*/
+{
+ PCONSOLE_CONTEXT Context;
+
+ Context = &BlFileTable[*FileId].u.ConsoleContext;
+ if ( strstr(OpenPath, ")console(1)" ) != NULL ) {
+ Context->ConsoleNumber = 1;
+ } else {
+ Context->ConsoleNumber = 0;
+ }
+
+ return ESUCCESS;
+}
+
+#ifndef FAILSAFE_BOOTER
+ARC_STATUS
+DisplayRead (
+ IN ULONG FileId,
+ IN PVOID Buffer,
+ IN ULONG Length,
+ OUT PULONG Count
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ return(ESUCCESS);
+}
+#endif // ndef FAILSAFE_BOOTER
+
+
+ARC_STATUS
+DisplayGetReadStatus (
+ IN ULONG FileId
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ return ESUCCESS;
+}
+
+
+ARC_STATUS
+DisplayWrite (
+ IN ULONG FileId,
+ IN PVOID Buffer,
+ IN ULONG Length,
+ OUT PULONG Count
+ )
+
+/*++
+
+Routine Description:
+
+ This module implements the ARC firmware Console Output functions as
+ described in the Advanced Risc Computing Specification (Revision 1.00),
+ section 3.3.1.5.1 Basic Character Console, and section 3.3.1.5.2 Enhanced
+ Character Console for a MIPS R3000 or R4000 Jazz system.
+
+
+Arguments:
+
+ FileId - Supplies a file id.
+
+ Buffer - Supplies a pointer to a buffer containing the characters to
+ be displayed.
+
+ Length - Supplies the length of Buffer.
+
+ Count - Returns the count of the characters that were displayed.
+
+Return Value:
+
+ If the characters were successfully displayed, ESUCCESS is returned,
+ otherwise one of the following error codes is returned.
+
+ EBADF The file descriptor specified by FileId is invalid.
+
+ EIO An output error occurred.
+
+--*/
+
+{
+ PCONSOLE_CONTEXT Context;
+ ARC_STATUS Status;
+ PUCHAR String;
+ ULONG ColumnEndPoint;
+ ULONG RowEndPoint;
+ ULONG Index;
+ BOOLEAN Unicode;
+
+ Context = &BlFileTable[FileId].u.ConsoleContext;
+ if ( Context->ConsoleNumber == 1) {
+ if (Length & 1) {
+
+ //
+ // Length is not an even number of bytes, return an error.
+ //
+
+ return(EINVAL);
+ }
+ Unicode = TRUE;
+ } else {
+ Unicode = FALSE;
+ }
+
+ //
+ // Process each character in turn.
+ //
+
+ Status = ESUCCESS;
+ String = (PUCHAR)Buffer;
+
+ for ( *Count = 0 ;
+ *Count < Length ;
+ (*Count)++, String++ ) {
+
+ //
+ // Check for Unicode character.
+ //
+
+ if (Unicode) {
+ if (*Count & 1) {
+
+ //
+ // Skip the upper half of each character.
+ //
+
+ continue;
+ } else {
+ if (*(String + 1) == 0x25) {
+
+ //
+ // If a Unicode line drawing character, go ahead and display
+ // it.
+ //
+
+ if (*String <= 0x7f) {
+ FwDisplayCharacter(*String, TRUE);
+ } else {
+ FwDisplayCharacter(128, TRUE);
+ }
+
+ if (FwColumn < MaxColumn) {
+ FwColumn++;
+ }
+ continue;
+ } else {
+ if (*(String + 1) != 0) {
+
+ //
+ // Display an invalid character.
+ //
+
+ FwDisplayCharacter(128, TRUE);
+
+ if (FwColumn < MaxColumn) {
+ FwColumn++;
+ }
+ continue;
+ }
+ }
+ }
+ }
+
+ //
+ // If we are in the middle of a control sequence, continue scanning,
+ // otherwise process character.
+ //
+
+ if (ControlSequence) {
+
+ //
+ // If the character is a digit, update parameter value.
+ //
+
+ if ((*String >= '0') && (*String <= '9')) {
+ Parameter[PCount] = Parameter[PCount] * 10 + *String - '0';
+ continue;
+ }
+
+ //
+ // If we are in the middle of a font selection sequence, this
+ // character must be a 'D', otherwise reset control sequence.
+ //
+
+ if (FontSelection) {
+
+ //if (*String == 'D') {
+ //
+ // //
+ // // Other fonts not implemented yet.
+ // //
+ //
+ //} else {
+ //}
+
+ ControlSequence = FALSE;
+ FontSelection = FALSE;
+ continue;
+ }
+
+ switch (*String) {
+
+ //
+ // If a semicolon, move to the next parameter.
+ //
+
+ case ';':
+
+ PCount++;
+ if (PCount > CONTROL_SEQUENCE_MAX_PARAMETER) {
+ PCount = CONTROL_SEQUENCE_MAX_PARAMETER;
+ }
+ Parameter[PCount] = 0;
+ break;
+
+ //
+ // If a 'J', erase part or all of the screen.
+ //
+
+ case 'J':
+
+ switch (Parameter[0]) {
+
+ //
+ // Erase to end of the screen.
+ //
+
+ case 0:
+ //
+ // Clear to end of line by Writing char ' '
+ //
+ ColumnEndPoint = FwColumn;
+ while (FwColumn <= MaxColumn) {
+ FwDisplayCharacter(' ', FALSE);
+ FwColumn++;
+ }
+ FwColumn = ColumnEndPoint;
+ if ((FwRow+1) <= MaxRow) {
+ //
+ // Zero the rest of the screen
+ //
+ FillVideoMemory((PUCHAR)(VIDEO_MEMORY + ((FwRow*2) * DisplayWidth)),
+ (DisplayHeight - FwRow - 1) * DisplayWidth,
+ FwBackgroundColor
+ );
+ }
+ break;
+
+ //
+ // Erase from the beginning of the screen.
+ //
+
+ case 1:
+ if (FwRow) {
+ FillVideoMemory((PUCHAR)(VIDEO_MEMORY),
+ (FwRow * DisplayWidth),
+ FwBackgroundColor
+ );
+ }
+ ColumnEndPoint=FwColumn;
+ for (FwColumn=0; FwColumn < ColumnEndPoint; FwColumn++) {
+ FwDisplayCharacter(' ', FALSE);
+ }
+ break;
+
+ //
+ // Erase entire screen.
+ //
+
+ default :
+ FillVideoMemory(VIDEO_MEMORY,
+ (DisplayWidth * DisplayHeight),
+ FwBackgroundColor);
+ FwRow = 0;
+ FwColumn = 0;
+ break;
+ }
+
+ ControlSequence = FALSE;
+ break;
+
+ //
+ // If a 'K', erase part or all of the line.
+ //
+
+ case 'K':
+
+ switch (Parameter[0]) {
+
+ //
+ // Erase to end of the line.
+ //
+
+ case 0:
+ ColumnEndPoint = FwColumn;
+ FwColumn = MaxColumn + 1;
+ do {
+ FwColumn--;
+ FwDisplayCharacter(' ', FALSE);
+ } while (FwColumn != ColumnEndPoint);
+ break;
+
+ //
+ // Erase from the beginning of the line.
+ //
+
+ case 1:
+ ColumnEndPoint = FwColumn;
+ FwColumn = -1;
+ do {
+ FwColumn++;
+ FwDisplayCharacter(' ', FALSE);
+ } while (FwColumn != ColumnEndPoint);
+ break;
+
+ //
+ // Erase entire line.
+ //
+
+ default :
+ FwColumn = MaxColumn + 1;
+ do {
+ FwColumn--;
+ FwDisplayCharacter(' ', FALSE);
+ } while (FwColumn != 0);
+ break;
+ }
+
+ ControlSequence = FALSE;
+ break;
+
+ //
+ // If a 'H', move cursor to position.
+ //
+
+ case 'H':
+
+ //
+ // Shift parameters to be 0 based.
+ //
+
+ if (Parameter[0] != 0) {
+ Parameter[0] -= 1;
+ }
+ if (Parameter[1] != 0) {
+ Parameter[1] -= 1;
+ }
+
+ FwRow = Parameter[0];
+ if (FwRow > MaxRow) {
+ FwRow = MaxRow;
+ }
+ FwColumn = Parameter[1];
+ if (FwColumn > MaxColumn) {
+ FwColumn = MaxColumn;
+ }
+
+ ControlSequence = FALSE;
+ break;
+
+ //
+ // If a 'A', move cursor up.
+ //
+
+ case 'A':
+
+ //
+ // A parameter of zero still means a cursor shift position of 1.
+ //
+
+ if (Parameter[0] == 0) {
+ Parameter[0] = 1;
+ }
+
+ if (Parameter[0] > FwRow) {
+ FwRow = 0;
+ } else {
+ FwRow -= Parameter[0];
+ }
+ ControlSequence = FALSE;
+ break;
+
+ //
+ // If a 'B', move cursor down.
+ //
+
+ case 'B':
+
+ //
+ // A parameter of zero still means a cursor shift position of 1.
+ //
+
+ if (Parameter[0] == 0) {
+ Parameter[0] = 1;
+ }
+
+ if (Parameter[0] + FwRow > MaxRow) {
+ FwRow = MaxRow;
+ } else {
+ FwRow += Parameter[0];
+ }
+ ControlSequence = FALSE;
+ break;
+
+ //
+ // If a 'C', move cursor right.
+ //
+
+ case 'C':
+
+ //
+ // A parameter of zero still means a cursor shift position of 1.
+ //
+
+ if (Parameter[0] == 0) {
+ Parameter[0] = 1;
+ }
+
+ if (Parameter[0] + FwColumn > MaxColumn) {
+ FwColumn = MaxColumn;
+ } else {
+ FwColumn += Parameter[0];
+ }
+ ControlSequence = FALSE;
+ break;
+
+ //
+ // If a 'D', move cursor left.
+ //
+
+ case 'D':
+
+ //
+ // A parameter of zero still means a cursor shift position of 1.
+ //
+
+ if (Parameter[0] == 0) {
+ Parameter[0] = 1;
+ }
+
+ if (Parameter[0] > FwColumn) {
+ FwColumn = 0;
+ } else {
+ FwColumn -= Parameter[0];
+ }
+ ControlSequence = FALSE;
+ break;
+
+ //
+ // If a ' ', could be a FNT selection command.
+ //
+
+ case ' ':
+ FontSelection = TRUE;
+ break;
+
+ //
+ // If a 'm', Select Graphics Rendition command.
+ //
+
+ case 'm':
+
+ //
+ // Select action based on each parameter.
+ //
+
+ for ( Index = 0 ; Index <= PCount ; Index++ ) {
+ switch (Parameter[Index]) {
+
+ //
+ // Attributes off.
+ //
+
+ case 0:
+ FwHighIntensity = FALSE;
+ FwUnderscored = FALSE;
+ FwReverseVideo = FALSE;
+ break;
+
+ //
+ // High Intensity.
+ //
+
+ case 1:
+ FwHighIntensity = TRUE;
+ break;
+
+ //
+ // Underscored.
+ //
+
+ case 4:
+ FwUnderscored = TRUE;
+ break;
+
+ //
+ // Reverse Video.
+ //
+
+ case 7:
+ FwReverseVideo = TRUE;
+ break;
+
+ //
+ // Font selection, not implemented yet.
+ //
+
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ case 16:
+ case 17:
+ case 18:
+ case 19:
+ break;
+
+ //
+ // Foreground Color.
+ //
+
+ case 30:
+ case 31:
+ case 32:
+ case 33:
+ case 34:
+ case 35:
+ case 36:
+ case 37:
+ FwForegroundColor = Parameter[Index] - 30;
+ break;
+
+ //
+ // Background Color.
+ //
+
+ case 40:
+ case 41:
+ case 42:
+ case 43:
+ case 44:
+ case 45:
+ case 46:
+ case 47:
+ FwBackgroundColor = Parameter[Index] - 40;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ ControlSequence = FALSE;
+ break;
+
+ default:
+ ControlSequence = FALSE;
+ break;
+ }
+
+ //
+ // This is not a control sequence, check for escape sequence
+ //
+
+ } else {
+
+ //
+ // If escape sequence, check for control sequence, otherwise
+ // process single character.
+ //
+
+ if (EscapeSequence) {
+
+ //
+ // Check for '[', means control sequence, any other following
+ // character is ignored.
+ //
+
+ if (*String == '[') {
+
+ ControlSequence = TRUE;
+
+ //
+ // Initialize first parameter.
+ //
+
+ PCount = 0;
+ Parameter[0] = 0;
+ }
+ EscapeSequence = FALSE;
+
+ //
+ // This is not a control or escape sequence, process single character.
+ //
+
+ } else {
+
+ //
+ // Check for special characters.
+ //
+
+ switch (*String) {
+
+ //
+ // Control sequence.
+ //
+
+ case ASCII_CSI:
+ ControlSequence = TRUE;
+
+ //
+ // Initialize first parameter.
+ //
+
+ PCount = 0;
+ Parameter[0] = 0;
+ break;
+
+ //
+ // Check for escape sequence.
+ //
+
+ case ASCII_ESC:
+ EscapeSequence = TRUE;
+ break;
+
+ //
+ // Vertical tab/Form feed Line feed.
+ //
+
+ case ASCII_LF:
+ case ASCII_VT:
+ case ASCII_FF:
+ if (FwRow == MaxRow) {
+ FwScrollDisplay();
+ } else {
+ FwRow++;
+ }
+
+ break;
+
+ //
+ // Carriage return.
+ //
+
+ case ASCII_CR:
+ FwColumn = 0;
+ break;
+
+ //
+ // NUL, no action.
+ //
+
+ case ASCII_NUL:
+ break;
+
+ //
+ // Ring bell, not implemented yet.
+ //
+
+ case ASCII_BEL:
+ break;
+
+ //
+ // Backspace.
+ //
+
+ case ASCII_BS:
+ if (FwColumn != 0) {
+ FwColumn--;
+ }
+ break;
+
+ //
+ // Horizontal tab.
+ //
+
+ case ASCII_HT:
+ FwColumn = ((FwColumn / 8) + 1) * 8;
+ if (FwColumn > MaxColumn) {
+ FwColumn = MaxColumn;
+ }
+ break;
+
+
+ //
+ // A printing character. If undefined, it will be
+ // displayed as a solid block.
+ //
+
+ default:
+
+ FwDisplayCharacter(*String, FALSE);
+
+ if (FwColumn < MaxColumn) {
+ FwColumn++;
+ }
+
+ break;
+ }
+ }
+ }
+ }
+
+ return Status;
+}
+
+ARC_STATUS
+DisplaySeek (
+ IN ULONG FileId,
+ IN PLARGE_INTEGER Offset,
+ IN SEEK_MODE SeekMode
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+ ESUCCESS is returned.
+
+--*/
+
+{
+ return ESUCCESS;
+}
+
+
+
+#if 0 // Needed only if Number9 GXE MClock needs to be reset to 45.000 MHz
+
+ULONG
+Number9_S3928_SetClock(
+ clock_value
+ )
+register long clock_value; /* 7bits M, 7bits N, 2bits P */
+
+/*++
+
+Routine Description:
+
+ This function sets up the clock registers on the Number 9 GXE board,
+ which has an S3 928 chip. This code came from Number 9 Corporation.
+ I will eventually make the code conform to Microsoft coding standards.
+
+
+Arguments:
+
+ clock_value The magic number that this function needs to
+ correctly initialize the board.
+
+Return Value:
+
+ Some other magic number is returned.
+
+--*/
+{
+ register long index;
+ long temp;
+// register char iotemp;
+ unsigned char iotemp;
+ int select;
+
+ long i, j;
+ unsigned char byte;
+
+ select = (clock_value >> 22) & 3;
+
+#if 0 // hack - Put this back in if going for GXE bugfix
+
+//
+// Already done before this point by the Video initialization table.
+//
+ //
+ // Unlock the S3 registers
+ //
+
+ WRITE_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_WRITE->crtc_address, 0x39);
+ WRITE_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_WRITE->crtc_data, 0xa0);
+
+#endif // hack - Put this back in if going for GXE bugfix
+
+
+#if 0 // hack - Put this back in if going for GXE bugfix
+
+//
+// This is not necessary.
+//
+ //
+ // Shut off screen
+ //
+
+ WRITE_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_WRITE->sequencer_address, 0x1);
+ iotemp = READ_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_READ->sequencer_data);
+ WRITE_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_WRITE->sequencer_data,
+ iotemp | 0x20);
+//
+
+#endif // hack - Put this back in if going for GXE bugfix
+
+ //
+ // set clock input to 11 binary
+ //
+
+ iotemp = READ_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_READ->misc_output);
+#ifdef ALPHA_FW_VDB
+ DebugAid[0][112] = iotemp;
+#endif
+ WRITE_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_WRITE->misc_output,
+ iotemp | 0x0C);
+
+ WRITE_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_WRITE->crtc_address, 0x5c);
+ WRITE_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_WRITE->crtc_data, 0);
+
+ WRITE_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_WRITE->crtc_address, 0x42);
+ iotemp = READ_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_READ->crtc_data) & 0xF0;
+#ifdef ALPHA_FW_VDB
+ DebugAid[0][113] = iotemp;
+#endif
+
+ //
+ // Set up the softswitch write value
+ //
+
+#define CLOCK(x) WRITE_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_WRITE->crtc_data, iotemp | (x))
+#define C_DATA 2
+#define C_CLK 1
+#define C_BOTH 3
+#define C_NONE 0
+
+ //
+ // Program the IC Designs 2061A frequency generator
+ //
+
+ CLOCK(C_NONE);
+
+ //
+ // Unlock sequence
+ //
+
+ CLOCK(C_DATA);
+ for (index = 0; index < 6; index++)
+ {
+ CLOCK(C_BOTH);
+ CLOCK(C_DATA);
+ }
+ CLOCK(C_NONE);
+ CLOCK(C_CLK);
+ CLOCK(C_NONE);
+ CLOCK(C_CLK);
+
+ //
+ // Program the 24 bit value into REG0
+ //
+
+ for (index = 0; index < 24; index++)
+ {
+ // Clock in the next bit
+ clock_value >>= 1;
+ if (clock_value & 1)
+ {
+ CLOCK(C_CLK);
+ CLOCK(C_NONE);
+ CLOCK(C_DATA);
+ CLOCK(C_BOTH);
+ }
+ else
+ {
+ CLOCK(C_BOTH);
+ CLOCK(C_DATA);
+ CLOCK(C_NONE);
+ CLOCK(C_CLK);
+ }
+ }
+
+ CLOCK(C_BOTH);
+ CLOCK(C_DATA);
+ CLOCK(C_BOTH);
+
+ //
+ // If necessary, reprogram other ICD2061A registers to defaults
+ //
+
+ //
+ // Select the CLOCK in the frequency synthesizer
+ //
+ CLOCK(C_NONE | select);
+
+ FwStallExecution(10*1000); // Stall 10 ms to let clock settle...
+
+
+
+#if 0 // hack - Put this back in if going for GXE bugfix
+
+//
+// This is not necessary.
+//
+ //
+ // Turn screen back on
+ //
+ WRITE_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_WRITE->sequencer_address, 0x01);
+ iotemp = READ_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_READ->sequencer_data);
+ WRITE_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_WRITE->sequencer_data,
+ iotemp & 0xDF);
+//
+
+#endif // hack - Put this back in if going for GXE bugfix
+
+
+ return temp;
+}
+#endif // Number9_S3928_SetClock
+
+
+//
+// This code came from ATI. It will be edited as per the Microsoft
+// coding standards at a later date.
+//
+
+/*
+;----------------------------------------------------------------------
+; SET_BLANK_ADJ
+; Sets the blank adjust and pixel delay values
+; INPUT: blank adjust and pixel delay
+;----------------------------------------------------------------------
+*/
+
+
+VOID
+Set_blank_adj(
+ UCHAR adjust
+ )
+{
+ UCHAR misc;
+
+ // ROM Page Select and EEPROM Control Register
+ misc=READ_PORT_UCHAR((PUCHAR)(R_MISC_CNTL + 1)) & 0xf0 | adjust;
+
+ WRITE_PORT_UCHAR((PUCHAR)(MISC_CNTL + 1), misc);
+
+}
+
+
+
+/************************************************************************
+ * passth_8514()
+ * Turn passthrough off (8514 mode) or on (vga passthrough)
+ * Note that this routine is specific to ATI graphics accelerators.
+ * Generic 8514/A routine should also include setting up CRT parameters
+ * to ensure that the DAC gets a reasonable clock rate.
+ ************************************************************************/
+
+VOID
+passth_8514(
+ IN BOOLEAN status
+ )
+{
+ // disable CRT controller
+ WRITE_PORT_UCHAR((PUCHAR)DISP_CNTL, 0x53);
+
+ if (status == FALSE) {
+ // Advanced function control
+ WRITE_PORT_USHORT((PUSHORT)ADVFUNC_CNTL, 0x7);
+ // Clock Select
+ WRITE_PORT_USHORT((PUSHORT)CLOCK_SEL,
+ READ_PORT_USHORT((PUSHORT)CLOCK_SEL) |
+ 1); // slow down the clock rate
+ } else {
+ // Advanced function control
+ WRITE_PORT_USHORT((PUSHORT)ADVFUNC_CNTL, 0x6);
+ // Clock Select
+ WRITE_PORT_USHORT((PUSHORT)CLOCK_SEL,
+ READ_PORT_USHORT((PUSHORT)CLOCK_SEL) &
+ 0xfffe); // speed up the clock rate
+
+ }
+
+ // enable CRT controller
+ WRITE_PORT_UCHAR((PUCHAR)DISP_CNTL, 0x33);
+}
+
+
+/*
+;----------------------------------------------------------------------
+; UNINIT_TI_DAC
+; Prepare DAC for 8514/A compatible mode
+;----------------------------------------------------------------------
+*/
+
+
+VOID
+Uninit_ti_dac(
+ VOID
+ )
+{
+ passth_8514(FALSE); // can only program DAC in 8514 mode
+
+#if 0
+
+ // Configuration status register 1.
+ switch (READ_PORT_UCHAR((PUCHAR)(CONFIG_STATUS_1 + 1)) & 0xe) {
+
+ case TI_DAC:
+
+ /* set EXT_DAC_ADDR field */
+
+ WRITE_PORT_USHORT((PUSHORT)EXT_GE_CONFIG, 0x201a);
+
+ /* INPut clock source is CLK0 */
+
+ WRITE_PORT_UCHAR ((PUCHAR)INPUT_CLK_SEL,0);
+
+ /* OUTPut clock is SCLK/1 and VCLK/1 */
+
+ WRITE_PORT_UCHAR ((PUCHAR)OUTPUT_CLK_SEL,0);
+
+ /* set MUX CONTROL TO 8/16 */
+
+ WRITE_PORT_UCHAR ((PUCHAR)MUX_CNTL,0x1d);
+
+ /* set default 8bpp pixel delay and blank adjust */
+
+ WRITE_PORT_USHORT ((PUSHORT)LOCAL_CNTL,
+ READ_PORT_USHORT((PUSHORT)LOCAL_CNTL) |
+ 8); // TI_DAC_BLANK_ADJUST is always on
+
+ Set_blank_adj(0xc);
+
+ /* set horizontal skew */
+
+ WRITE_PORT_UCHAR ((PUCHAR)HORIZONTAL_OVERSCAN,1);
+ break;
+
+
+ case ATT_DAC:
+
+ WRITE_PORT_USHORT((PUSHORT)EXT_GE_CONFIG,0x101a);
+ WRITE_PORT_UCHAR((PUCHAR)ATT_MODE_CNTL,0);
+
+
+ default:
+
+ /* PIXEL_DELAY=0 */
+
+ Set_blank_adj(0);
+
+ /* set horizontal skew */
+
+ WRITE_PORT_USHORT((PUSHORT)HORIZONTAL_OVERSCAN,0);
+ break;
+ }
+#else
+
+ // Configuration status register 1.
+ switch (READ_PORT_UCHAR((PUCHAR)(CONFIG_STATUS_1 + 1)) & 0xe) {
+
+ case TI_DAC:
+
+ /* set EXT_DAC_ADDR field */
+
+ WRITE_PORT_USHORT((PUSHORT)EXT_GE_CONFIG, 0x201a);
+
+ /* INPut clock source is CLK0 */
+
+ WRITE_PORT_UCHAR ((PUCHAR)INPUT_CLK_SEL,0);
+
+ /* OUTPut clock is SCLK/1 and VCLK/1 */
+
+ WRITE_PORT_UCHAR ((PUCHAR)OUTPUT_CLK_SEL,0);
+
+ /* set MUX CONTROL TO 8/16 */
+
+ WRITE_PORT_UCHAR ((PUCHAR)MUX_CNTL,0x1d);
+
+ /* set default 8bpp pixel delay and blank adjust */
+
+ WRITE_PORT_USHORT ((PUSHORT)LOCAL_CNTL,
+ READ_PORT_USHORT((PUSHORT)LOCAL_CNTL) |
+ 8); // TI_DAC_BLANK_ADJUST is always on
+
+ Set_blank_adj(0xc);
+
+ /* set horizontal skew */
+
+ WRITE_PORT_UCHAR ((PUCHAR)HORIZONTAL_OVERSCAN,1);
+ break;
+
+
+ case ATT_DAC:
+
+ WRITE_PORT_USHORT((PUSHORT)EXT_GE_CONFIG,0x101a);
+ WRITE_PORT_UCHAR((PUCHAR)ATT_MODE_CNTL,0);
+
+
+ default:
+
+ /* PIXEL_DELAY=0 */
+
+ Set_blank_adj(4);
+
+ WRITE_PORT_USHORT((PUSHORT)EXT_GE_CONFIG, 0xa);
+
+ WRITE_PORT_UCHAR((PUCHAR)DAC_MASK, 0xff);
+
+
+ /* set horizontal skew */
+
+ WRITE_PORT_USHORT((PUSHORT)HORIZONTAL_OVERSCAN,0);
+ break;
+ }
+
+#endif
+
+//
+// reset EXT_DAC_ADDR, put DAC in 6 bit mode, engine in 8 bit mode
+//
+ WRITE_PORT_USHORT((PUSHORT)EXT_GE_CONFIG,0x1a);
+ passth_8514(TRUE);
+
+ return;
+}
+
+
+#if 0 // hack - Put this back in if going for GXE bugfix.
+
+//
+// At one point this was thought to be necessary for video initialization.
+//
+
+VOID
+DoAWaitForVerticalSync(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This waits for the beginning of a vertical sync.
+
+ BUG: There is no indication of whether the vertical sync really
+ has begun or if we timed out.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ ULONG I;
+
+ // First wait for being in a vertical blanking period.
+
+ for (I = 0; I < 0x100000; I++) {
+ if (READ_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_READ->input_status_1) & 0x08) {
+ break;
+ }
+ }
+
+ //
+ // We are either in a vertical blanking interval or we have timed out.
+ // Wait for the vertical display interval.
+ // This is being done so that we ensure that we exit this routine at
+ // the *beginning* of a vertical blanking interval, and not in the middle
+ // or near the end of one.
+ //
+
+ for (I = 0; I < 0x100000; I++) {
+ if (!(READ_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_READ->input_status_1) & 0x08)) {
+ break;
+ }
+ }
+
+ // Now wait until we once again enter into a vertical blanking interval.
+
+ for (I = 0; I < 0x100000; I++) {
+ if (READ_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_READ->input_status_1) & 0x08) {
+ break;
+ }
+ }
+
+ return;
+}
+
+#endif // hack - Put this back in if going for GXE bugfix.
+
+
+ARC_STATUS
+DisplayBootInitialize (
+ OUT PALPHA_VIDEO_TYPE VideoType
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the video control registers, and clears the
+ video screen.
+
+Arguments:
+
+ VideoType A pointer to a variable that receives the
+ type of the video card found on an ESUCCESS
+ return.
+
+Return Value:
+
+ If the video was initialized, ESUCCESS is returned, otherwise an error
+ code is returned.
+
+--*/
+
+{
+#ifndef FAILSAFE_BOOTER
+ //
+ // Initialize the firmware routines.
+ //
+
+ (PARC_TEST_UNICODE_CHARACTER_ROUTINE)SYSTEM_BLOCK->FirmwareVector[TestUnicodeCharacterRoutine] =
+ FwTestUnicodeCharacter;
+
+ (PARC_GET_DISPLAY_STATUS_ROUTINE)SYSTEM_BLOCK->FirmwareVector[GetDisplayStatusRoutine] =
+ FwGetDisplayStatus;
+#endif
+
+
+
+ //
+ // Initialize static data.
+ //
+
+ ControlSequence = FALSE;
+ EscapeSequence = FALSE;
+ FontSelection = FALSE;
+ FwColumn = 0;
+ FwRow = 0;
+ FwHighIntensity = TRUE;
+ FwUnderscored = FALSE;
+ FwReverseVideo = FALSE;
+
+ return ( FwInitializeGraphicsCard(VideoType) );
+}
+
+ARC_STATUS
+FwInitializeGraphicsCard(
+ OUT PALPHA_VIDEO_TYPE VideoType
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the VGA video control registers and clears the
+ video screen.
+
+ It is initialized to: alphanumeric mode, 16 colors fore & background,
+ 8x16 pixel fonts, 80x25 characters, 640 x 400 display, no cursor.
+ This is not ARC compliant (no underline, no monochrome support)
+ but it's good enough for now.
+
+
+Arguments:
+
+ VideoType A pointer to a variable that receives the
+ type of the video card found on an ESUCCESS
+ return.
+
+
+Return Value:
+
+ If the video was initialized, ESUCCESS is returned, otherwise ENODEV
+ is returned.
+
+--*/
+
+{
+ ULONG I, J, K;
+ PUCHAR FontPtr;
+ ULONG VideoCardType;
+ ULONG VITIndex = 0;
+ BOOLEAN BadTable = FALSE;
+
+
+#ifdef ALPHA_FW_VDB
+ SerSnapshot = TRUE;
+
+ FwVideoStateDump(0);
+#endif
+
+ //
+ // If a recognized card type is not out there, return an error code.
+ //
+
+ if ((VideoCardType=FwDetermineCardType()) == 0) {
+ return ENODEV;
+ }
+
+ //
+ // Interpret the Video Initialization Table
+ //
+
+ do {
+
+ if (VideoInitializationTable[VITIndex].DoIf & VideoCardType) {
+
+ //
+ // Execute this table entry
+ //
+
+
+ switch (VideoInitializationTable[VITIndex].Operation) {
+
+
+ //
+ // Do a read
+ //
+
+ case Read:
+
+ switch (VideoInitializationTable[VITIndex].Size) {
+
+ case UChar:
+ READ_PORT_UCHAR(VideoInitializationTable[VITIndex].Address);
+ break;
+
+ case UShort:
+ READ_PORT_USHORT((PUSHORT)VideoInitializationTable[VITIndex].Address);
+ break;
+
+ case ULong:
+ READ_PORT_ULONG((PULONG)VideoInitializationTable[VITIndex].Address);
+ break;
+
+ //
+ // Malformed table!
+ //
+
+ default:
+ BadTable = TRUE;
+ break;
+ }
+
+ break;
+
+
+ //
+ // Do a write
+ //
+
+ case Write:
+
+ switch (VideoInitializationTable[VITIndex].Size) {
+
+ case UChar:
+ WRITE_PORT_UCHAR(VideoInitializationTable[VITIndex].Address,
+ VideoInitializationTable[VITIndex].WriteValue);
+ break;
+
+ case UShort:
+ WRITE_PORT_USHORT((PUSHORT)VideoInitializationTable[VITIndex].Address,
+ VideoInitializationTable[VITIndex].WriteValue);
+ break;
+
+ case ULong:
+ WRITE_PORT_ULONG((PULONG)VideoInitializationTable[VITIndex].Address,
+ VideoInitializationTable[VITIndex].WriteValue);
+ break;
+
+
+ //
+ // Malformed table!
+ //
+
+ default:
+ BadTable = TRUE;
+ break;
+
+ }
+
+ break;
+
+
+ //
+ // Load the fonts into bit plane 2.
+ //
+
+ case LoadFonts:
+
+ // Instead of calling a function, we do the work here.
+
+ for (I=0; I<256; ++I) {
+
+ if ((I >= 0x20) && (I <= 0x7f)) {
+ // Normal printing characters
+ FontPtr = &VGA8x16Chars[16 * (I-0x20)];
+#ifndef FAILSAFE_BOOTER
+ } else if ((I >= 0xb3) && (I <= 0xda)) {
+ // Line drawing characters
+ FontPtr = &VGA8x16LineDrawing[16 * (I-0xb3)];
+#endif
+ } else {
+ // Undefined characters
+ FontPtr = &VGA8x16Undef[0];
+ }
+
+ K = 32 * I;
+
+ //
+ // 8x16 = 16 lines used, 16 lines unused
+ //
+ // hack:
+ // VIDEO_MEMORY points is EISA 0xb8000. The bit plane
+ // for the fonts, with the memory map field encoding that
+ // has been written, is at EISA 0xa0000. (Page 196 of
+ // the Ferraro book.) I could change the MM encoding or
+ // just write to the different address. Since this is
+ // the only place where the fonts are loaded, I choose to
+ // use a hardcoded Alpha/Jensen QVA ISA address here.
+ // Time permitting, this should be cleaned up.
+ //
+ for (J=0; J<16; ++J) {
+ WRITE_REGISTER_UCHAR ((PUCHAR)EisaMemQva(0xa0000) + K + J,
+ *(FontPtr + J) );
+ WRITE_REGISTER_UCHAR ((PUCHAR)EisaMemQva(0xa0000) + K + (J+16),
+ 0xff );
+
+ }
+ }
+
+ break;
+
+#if 0 // Needed only if Number9 GXE MClock needs to be reset to 45.000 MHz
+ //
+ // Initialize S3 928 clock on a Number 9 board
+ //
+
+ case InitializeNumber9Clocks:
+
+ Number9_S3928_SetClock(0xeb5942); // 45.000
+ break;
+#endif
+
+ //
+ // Initialize ATI Mach 32 DAC
+ //
+
+ case InitializeATIMachDAC:
+ Uninit_ti_dac();
+ break;
+
+
+ //
+ // Do nothing.
+ //
+
+ case None:
+
+ break;
+
+
+ //
+ // Malformed table.
+ //
+
+ default:
+
+ BadTable = TRUE;
+ break;
+ }
+
+ //
+ // If the table is bad, stop now and return an error code.
+ //
+ if (BadTable) {
+ return ENODEV;
+ }
+
+
+ if (VideoInitializationTable[VITIndex].MB) {
+// AlphaInstMB();
+ }
+
+ }
+
+ }
+
+ while (VideoInitializationTable[++VITIndex].Operation !=
+ End_Of_Initialization);
+
+ //
+ // Initialize static data.
+ //
+
+ FwForegroundColor = FW_COLOR_WHITE;
+ FwBackgroundColor = FW_COLOR_BLUE;
+
+ DisplayWidth = 80;
+ DisplayHeight = 25;
+
+ MaxRow = DisplayHeight -1;
+ MaxColumn = DisplayWidth -1;
+
+ //
+ // Initialize the console context value for the display output so writes
+ // to the screen will work before the console is opened.
+ //
+
+ BlFileTable[ARC_CONSOLE_OUTPUT].u.ConsoleContext.ConsoleNumber = 0;
+
+
+ //
+ // Set the video memory to blue.
+ //
+
+ FillVideoMemory(VIDEO_MEMORY, DisplayWidth * DisplayHeight, FwBackgroundColor);
+
+ //
+ // Translate the bitmask video type to a ALPHA_VIDEO_TYPE, and return
+ // it in the output variable.
+ //
+
+ switch (VideoCardType) {
+
+ case Paradise_WD90C11:
+ *VideoType = _Paradise_WD90C11;
+ break;
+
+ case Compaq_QVision:
+ *VideoType = _Compaq_QVision;
+ break;
+
+ case Cardinal_S3_924:
+ *VideoType = _Cardinal_S3_924;
+ break;
+
+ case S3_928:
+ *VideoType = _S3_928;
+ break;
+
+#if 0
+ case ATI_Mach:
+ *VideoType = _ATI_Mach;
+ break;
+#endif
+
+ default:
+ // Internal error.
+ return ENODEV;
+ }
+
+
+#ifdef ALPHA_FW_VDB
+ FwVideoStateDump(1);
+#endif
+
+ return ESUCCESS;
+}
+
+ULONG
+FwDetermineCardType (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This determines the kind of video card in this system.
+
+ We do not use the CDS graphics information because it leads to a chicken
+ and egg problem: if the CDS information is wrong, we will initialize
+ the video incorrectly and therefore not be able to communicate with the
+ user; and if we were to determine that the CDS information is wrong, we
+ would proceed to sniff the I/O bus anyway. Hence, we ignore the CDS for
+ booting.
+
+ Some VGA and card or chip specific registers need to be modified by this
+ function. The card should be initialized after this function is called.
+
+
+Arguments:
+
+ None.
+
+
+Return Value:
+
+ Zero if we cannot figure out what card is installed.
+ Otherwise, a bit mask indicating the card present.
+
+--*/
+
+{
+ ULONG EISAProductID;
+ USHORT EISAProductIDHighWord, EISAProductIDLowWord;
+ PULONG EISAProductIDAddress;
+ ULONG Card = 0;
+ BOOLEAN Success = FALSE;
+ ULONG I;
+ UCHAR TempX;
+
+
+#ifdef EISA_PLATFORM
+
+ //
+ // Test for EISA cards in option slots
+ //
+
+ for (I = 1; I <= MAXIMUM_EISA_SLOTS; I++) {
+
+ //
+ // Get this slot's product ID
+ //
+
+ EISAProductIDAddress = (PULONG)(EISA_IO_VIRTUAL_BASE + (I<<12) + 0xC80);
+ EISAProductID = READ_PORT_ULONG(EISAProductIDAddress);
+ EISAProductIDHighWord = EISAProductID >> 16;
+ EISAProductIDLowWord = EISAProductID & 0xffff;
+
+ //
+ // Test for Compaq QVision 1024/E or Compaq QVision Orion 1280/E.
+ //
+
+ if ((EISAProductIDLowWord == 0x110E) // "CPQ"
+ &&
+ ((EISAProductIDHighWord == 0x1130) // TRITONE, aka QVision 1024/E
+ ||
+ (EISAProductIDHighWord == 0x1131) // Orion 1024/E
+ ||
+ (EISAProductIDHighWord == 0x1231) // Orion 1280/E
+ )
+ ) {
+ Success = TRUE;
+ Card = Compaq_QVision;
+ break;
+ }
+
+ }
+
+ if (Success) {
+ return (Card);
+ }
+
+#endif // EISA_PLATFORM
+
+
+ //
+ // No EISA video cards, so test for ISA cards.
+ //
+
+
+ //
+ // Test for boards with S3 911, 924, or 928 chips.
+ //
+
+ // HACKHACK: These addresses should be #define'd.
+
+ // Put video subsystem into setup mode
+ WRITE_PORT_UCHAR((PUCHAR)EisaIOQva(0x46e8), 0x10);
+
+ // Turn on the video subsystem.
+ WRITE_PORT_UCHAR((PUCHAR)EisaIOQva(0x0102), 0x01);
+
+ // Enable the video subsystem. This may be unnecessary for some cards.
+ WRITE_PORT_UCHAR((PUCHAR)EisaIOQva(0x46e8), 0x08);
+
+ // Set the card to color-mode addressing.
+ WRITE_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_WRITE->misc_output,
+ (READ_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_READ->misc_output)
+ | 0x1));
+
+ // Unlock the S3 chip VGA S3 registers
+ WRITE_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_WRITE->crtc_address, VGA_S3924_S3R8);
+ WRITE_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_WRITE->crtc_data, 0x48);
+
+ // Read the chip ID/Rev register
+ WRITE_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_WRITE->crtc_address, VGA_S3924_S3R0);
+ TempX = READ_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_WRITE->crtc_data);
+
+#ifdef ALPHA_FW_VDB
+ DebugAid[0][0] = TempX;
+#endif
+
+ switch (TempX) {
+
+ case 0x81:
+ case 0x82:
+
+ //
+ // Conclusion: this is an S3 911 or 924 -based video board.
+ // (0x81 = 911, 0x82 = 924)
+ //
+
+ return (Cardinal_S3_924);
+
+
+ case 0x90:
+ case 0x91:
+ case 0x92:
+ case 0x93:
+
+ //
+ // Conclusion: this is an S3 928 -based video board.
+ // (rev. 0 -- rev. 3)
+ //
+
+ return (S3_928);
+ }
+
+ //
+ // Now test for Paradise board with Western Digital 90C11 chipset
+ //
+
+ // Wake up the board
+ WRITE_PORT_UCHAR((PUCHAR)EisaIOQva(0x46e8), 0x10);
+ WRITE_PORT_UCHAR((PUCHAR)EisaIOQva(0x0102), 0x1);
+ WRITE_PORT_UCHAR((PUCHAR)EisaIOQva(0x46e8), 0x8);
+
+ // Unlock PR0 -- PR4
+ WRITE_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_WRITE->graphics_address, 0x0f);
+ WRITE_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_WRITE->graphics_data, 0x5);
+ // Clear PR4<1> so that PR5 is readable.
+ WRITE_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_WRITE->graphics_address, 0x0e);
+ TempX = READ_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_WRITE->graphics_data);
+ WRITE_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_WRITE->graphics_address, 0x0e);
+ WRITE_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_WRITE->graphics_data, (TempX & 0xfd));
+
+ // Write and read the PR5 register a few times. PR5 is an extension
+ // (index = 0x0f) to the Graphics Controller Register set.
+
+ WRITE_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_WRITE->graphics_address, 0x0f);
+ WRITE_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_WRITE->graphics_data, 0x1);
+ WRITE_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_WRITE->graphics_address, 0x0f);
+ if (READ_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_WRITE->graphics_data) != 0x1) {
+ // test failed
+ goto Not_Paradise_Board;
+ }
+ WRITE_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_WRITE->graphics_address, 0x0f);
+ WRITE_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_WRITE->graphics_data, 0x4);
+ WRITE_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_WRITE->graphics_address, 0x0f);
+ if (READ_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_WRITE->graphics_data) != 0x4) {
+ // test failed
+ goto Not_Paradise_Board;
+ }
+ WRITE_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_WRITE->graphics_address, 0x0f);
+ WRITE_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_WRITE->graphics_data, 0x5);
+ WRITE_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_WRITE->graphics_address, 0x0f);
+ if (READ_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_WRITE->graphics_data) != 0x5) {
+ // test failed
+ goto Not_Paradise_Board;
+ }
+ WRITE_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_WRITE->graphics_address, 0x0f);
+ WRITE_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_WRITE->graphics_data, 0x0);
+ WRITE_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_WRITE->graphics_address, 0x0f);
+ if (READ_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_WRITE->graphics_data) != 0x0) {
+ // test failed
+ goto Not_Paradise_Board;
+ }
+
+ //
+ // I conclude that this is a Paradise board with a WD90Cxx chip.
+ //
+
+ return (Paradise_WD90C11);
+
+ //
+ // The test for a Paradise board failed.
+ //
+
+Not_Paradise_Board:
+
+ //
+ // If we get to here, we cannot identify any supported video cards.
+ //
+
+ return (0);
+
+}
+
+VOID
+FillVideoMemory (
+ IN volatile PUCHAR VideoBase,
+ IN ULONG FillLength,
+ IN ULONG FillColor
+ )
+
+/*++
+
+Routine Description:
+
+ Fills video memory with a specified color.
+
+Arguments:
+
+ VideoBase - pointer to the base of the fill area. This is a
+ video card memory address.
+
+ FillLength - number of screen characters to be filled.
+
+ FillColor - the fill (background) color.
+
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG I;
+
+ for (I = 0; I <= (FillLength * 2); I+=2) {
+ WRITE_REGISTER_UCHAR((PUCHAR)(VideoBase + I), ' ');
+ WRITE_REGISTER_UCHAR((PUCHAR)(VideoBase + (I+1)), (FillColor << 4));
+ }
+}
+
+VOID
+DisplayInitialize (
+ IN OUT PDRIVER_LOOKUP_ENTRY LookupTableEntry,
+ IN ULONG Entries
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the video entry in the driver lookup table.
+
+ The Jazz version of this also manipulated the ARC configuration tree.
+ Since we will only support VGA, we should be able to keep all this static
+ in the PROM.
+
+
+Arguments:
+
+ LookupTableEntry - Supplies a pointer to the first free location in the
+ driver lookup table.
+
+ Entries - Supplies the number of free entries in the driver lookup table.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Initialize the driver lookup table, and increment the pointer.
+ //
+
+ LookupTableEntry->DevicePath = FW_DISPLAY_DEVICE_PATH;
+ LookupTableEntry->DispatchTable = &DisplayEntryTable;
+
+ return;
+}
+
+VOID
+FwOutputCharacter (
+ IN UCHAR Character
+ )
+
+/*++
+
+Routine Description:
+
+ This routine displays a single character on the video screen at the current
+ cursor location with the current color and video attributes. It assumes
+ the character locations are word aligned.
+
+Arguments:
+
+ Character - Supplies the character to be displayed in the video
+ cards memory space.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG FGColor;
+ ULONG BGColor;
+ PUCHAR Destination;
+
+ // Map ASCII code 7 to bullet
+ if (Character == 7) {
+ Character = '~' + 1;
+ }
+
+ if (FwReverseVideo) {
+ FGColor = FwBackgroundColor;
+ BGColor = FwForegroundColor + (FwHighIntensity ? 0x08 : 0 );
+ } else {
+ FGColor = FwForegroundColor + (FwHighIntensity ? 0x08 : 0 );
+ BGColor = FwBackgroundColor;
+ }
+
+ Destination = (PUCHAR)(VIDEO_MEMORY +
+ ((FwRow << 1) * DisplayWidth) + (FwColumn << 1)
+ );
+
+ WRITE_REGISTER_UCHAR (Destination, (Character & 0xff));
+ WRITE_REGISTER_UCHAR ((Destination+1), ((BGColor << 4) | FGColor));
+
+}
+
+VOID
+FwDisplayCharacter (
+ IN UCHAR Character,
+ IN BOOLEAN LineDrawCharacter
+ )
+
+/*++
+
+Routine Description:
+
+ This routine displays a single character on the video screen at the current
+ cursor location with the current color and video attributes.
+
+ This is a no-op. Including it minimizes code differences with the
+ Jazz sources.
+
+Arguments:
+
+ Character - Supplies the character to be displayed.
+
+ LineDrawCharacter - If true the current character is a line drawing character.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ if (!LineDrawCharacter) {
+
+ FwOutputCharacter(Character);
+
+ } else {
+
+ FwOutputCharacter(Character);
+
+ }
+ return;
+}
+
+VOID
+FwScrollDisplay (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine scrolls the display up one line.
+
+ This assumes that FwRow is at the end of the screen, i.e.
+ FwRow == MaxRow.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ volatile PUCHAR Source, Destination;
+ int i;
+ ULONG SaveColumn;
+
+ for (i = (2 * DisplayWidth);
+ i < (2 * (DisplayWidth * DisplayHeight));
+ ++i) {
+
+ Source = VIDEO_MEMORY + i;
+ Destination = Source - (2 * DisplayWidth);
+ WRITE_REGISTER_UCHAR (Destination,
+ (READ_REGISTER_UCHAR (Source))
+ );
+
+ }
+
+ SaveColumn = FwColumn;
+
+ for (FwColumn = 0 ;
+ FwColumn <= MaxColumn ;
+ ++FwColumn ) {
+ FwDisplayCharacter(' ', FALSE);
+ }
+
+ FwColumn = SaveColumn;
+
+}
+
+#ifndef FAILSAFE_BOOTER
+ARC_STATUS
+FwTestUnicodeCharacter (
+ IN ULONG FileId,
+ IN WCHAR UnicodeCharacter
+ )
+/*++
+
+Routine Description:
+
+ This routine checks for the existence of a valid glyph corresponding to
+ UnicodeCharacter.
+
+Arguments:
+
+ FileId - Supplies the FileId of the output device.
+
+ UnicodeCharacter - Supplies the UNICODE character to be tested.
+
+Return Value:
+
+ If writing UnicodeCharacter to the device specified by FileId would
+ result in the display of a valid glyph on the output device, then
+ ESUCCESS is returned. If the device does not support the character,
+ the EINVAL is returned.
+
+--*/
+{
+ if (((UnicodeCharacter >= ' ') && (UnicodeCharacter <= '~')) ||
+ ((UnicodeCharacter >= 0x2500) && (UnicodeCharacter <= 0x257f))) {
+ return(ESUCCESS);
+ } else {
+ return(EINVAL);
+ }
+}
+#endif // FAILSAFE_BOOTER
+
+
+
+#ifndef FAILSAFE_BOOTER
+
+PARC_DISPLAY_STATUS
+FwGetDisplayStatus (
+ IN ULONG FileId
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ DisplayStatus.CursorXPosition = FwColumn + 1;
+ DisplayStatus.CursorYPosition = FwRow + 1;
+ DisplayStatus.CursorMaxXPosition = MaxColumn + 1;
+ DisplayStatus.CursorMaxYPosition = MaxRow + 1;
+ DisplayStatus.ForegroundColor = FwForegroundColor;
+ DisplayStatus.BackgroundColor = FwBackgroundColor;
+ DisplayStatus.HighIntensity = FwHighIntensity;
+ DisplayStatus.Underscored = FwUnderscored;
+ DisplayStatus.ReverseVideo = FwReverseVideo;
+
+ return(&DisplayStatus);
+}
+#endif // FAILSAFE_BOOTER
+
+
+
+#ifdef ALPHA_FW_VDB
+
+VOID
+FwVideoStateDump(
+ IN ULONG Index
+ )
+/*++
+
+Routine Description:
+
+ This function facilitates debugging video problems. It dumps
+ the state of the video card into an array. It is modified for the
+ particular video card under test.
+
+Arguments:
+
+ Index - Index into the DebugAid array. 0 for the first
+ state dump, 1 for the second, etc.
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // Status of S3 928 debugging: works fine
+ //
+ // Status of ATI Mach debugging:
+ //
+ // This has not been debugged yet. The screen remained blank. Mach
+ // support is either ifdefd out, or undebugged.
+ //
+
+ ULONG I;
+ UCHAR EISAData;
+ PUCHAR EISAAddress;
+ volatile UCHAR Temp;
+
+ //
+ // Generic VGA state
+ //
+
+ //
+ // External VGA registers.
+ //
+
+ //
+ // DebugAid[0][0] is already used.
+ //
+
+ DebugAid[Index][1] = READ_PORT_UCHAR (&VIDEO_CONTROL_READ->misc_output);
+ DebugAid[Index][2] = READ_PORT_UCHAR (&VIDEO_CONTROL_READ->feature_control);
+ DebugAid[Index][3] = READ_PORT_UCHAR (&VIDEO_CONTROL_READ->input_status_0);
+ DebugAid[Index][4] = READ_PORT_UCHAR (&VIDEO_CONTROL_READ->input_status_1);
+
+
+ //
+ // VGA Sequencer registers.
+ //
+
+ for (I = 0; I < 5; I++) {
+ WRITE_PORT_UCHAR (&VIDEO_CONTROL_WRITE->sequencer_address, I);
+ DebugAid [Index] [5 + I - 0] =
+ READ_PORT_UCHAR (&VIDEO_CONTROL_READ->sequencer_data);
+ }
+
+ //
+ // VGA CRTC registers.
+ //
+
+ for (I = 0; I < 0x19; I++) {
+ WRITE_PORT_UCHAR (&VIDEO_CONTROL_WRITE->crtc_address, I);
+ DebugAid [Index] [10 + I - 0] =
+ READ_PORT_UCHAR (&VIDEO_CONTROL_READ->crtc_data);
+ }
+
+ //
+ // VGA graphics registers.
+ //
+
+ for (I = 0; I < 9; I++) {
+ WRITE_PORT_UCHAR (&VIDEO_CONTROL_WRITE->graphics_address, I);
+ DebugAid [Index] [0x23 + I - 0] =
+ READ_PORT_UCHAR (&VIDEO_CONTROL_READ->graphics_data);
+ }
+
+#if 0
+ //
+ // VGA attribute registers, sans palette registers.
+ //
+
+ for (I = 0x10; I < 0x15; I++) {
+
+ // Reset attribute address register FF
+ Temp = READ_PORT_UCHAR((PUCHAR)&VIDEO_CONTROL_READ->input_status_1);
+
+ WRITE_PORT_UCHAR (&VIDEO_CONTROL_WRITE->attribute_adddata, I);
+ DebugAid [Index] [44 + I - 0x10] =
+ READ_PORT_UCHAR (&VIDEO_CONTROL_READ->attribute_adddata);
+ }
+
+#endif
+
+ //
+ // Video card specific state, Number9 GXE /w S3 928 chip.
+ //
+
+ //
+ // Unlock via cr38, cr39
+ //
+
+ WRITE_PORT_UCHAR (&VIDEO_CONTROL_WRITE->crtc_address, 0x38);
+ WRITE_PORT_UCHAR (&VIDEO_CONTROL_WRITE->crtc_data, 0x48);
+
+ WRITE_PORT_UCHAR (&VIDEO_CONTROL_WRITE->crtc_address, 0x39);
+ WRITE_PORT_UCHAR (&VIDEO_CONTROL_WRITE->crtc_data, 0xa0);
+
+ //
+ // spec page 7-1
+ //
+
+ for (I = 0x31; I < 0x3d; I++) {
+ WRITE_PORT_UCHAR (&VIDEO_CONTROL_WRITE->crtc_address, I);
+ DebugAid [Index] [49 + I - 0x31] =
+ READ_PORT_UCHAR (&VIDEO_CONTROL_READ->crtc_data);
+ }
+
+ //
+ // spec pages 8-1, 9-1
+ //
+
+ for (I = 0x40; I < 0x63; I++) {
+ WRITE_PORT_UCHAR (&VIDEO_CONTROL_WRITE->crtc_address, I);
+ DebugAid [Index] [61 + I - 0x40] =
+ READ_PORT_UCHAR (&VIDEO_CONTROL_READ->crtc_data);
+ }
+
+ //
+ // spec page 10-4
+ //
+
+ // advfunc_cntl
+ DebugAid[Index][96] = READ_PORT_USHORT((PUCHAR)EisaIOQva(0x46e8)) & 0xff;
+ DebugAid[Index][97] = (READ_PORT_USHORT((PUCHAR)EisaIOQva(0x46e8)) >> 8)
+ & 0xff;
+
+
+}
+
+#endif
diff --git a/private/ntos/fw/alpha/jxenvir.c b/private/ntos/fw/alpha/jxenvir.c
new file mode 100644
index 000000000..b31d38985
--- /dev/null
+++ b/private/ntos/fw/alpha/jxenvir.c
@@ -0,0 +1,1020 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ jxenvir.c
+
+Abstract:
+
+ This module implements the ARC firmware Environment Variable functions as
+ described in the Advanced Risc Computing Specification (Revision 1.00),
+ section 3.3.3.11, for a MIPS R3000 or R4000 Jazz system.
+
+Author:
+
+ David M. Robinson (davidro) 13-June-1991
+
+
+Revision History:
+
+ 26-May-1992 John DeRosa [DEC]
+
+ Added Alpha/Jensen hooks.
+
+
+--*/
+
+#include "fwp.h"
+//
+// Static data.
+//
+
+UCHAR OutputString[MAXIMUM_ENVIRONMENT_VALUE];
+PUCHAR VolatileEnvironment;
+
+//
+// Routine prototypes.
+//
+
+#ifdef MORGAN
+UCHAR
+HalpReadNVByte (
+ IN PUCHAR RAddress
+ );
+#endif
+
+ARC_STATUS
+FwEnvironmentSetChecksum (
+ VOID
+ );
+
+ARC_STATUS
+FwFindEnvironmentVariable (
+ IN PCHAR Variable,
+ OUT PULONG VariableIndex,
+ OUT PULONG ValueIndex
+ );
+
+ARC_STATUS
+FwFindVolatileEnvironmentVariable (
+ IN PCHAR Variable,
+ OUT PULONG VariableIndex,
+ OUT PULONG ValueIndex
+ );
+
+BOOLEAN
+EnvironmentVariableIsProtected (
+ IN PCHAR Variable
+ );
+
+VOID
+FwEnvironmentInitialize (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the environment routine addresses.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // Allocate enough memory to load the environment for loaded programs.
+ //
+
+ VolatileEnvironment = FwAllocatePool(LENGTH_OF_ENVIRONMENT);
+
+ //
+ // Initialize the environment routine addresses in the system
+ // parameter block.
+ //
+
+ (PARC_GET_ENVIRONMENT_ROUTINE)SYSTEM_BLOCK->FirmwareVector[GetEnvironmentRoutine] =
+ FwGetEnvironmentVariable;
+ (PARC_SET_ENVIRONMENT_ROUTINE)SYSTEM_BLOCK->FirmwareVector[SetEnvironmentRoutine] =
+ FwSetEnvironmentVariable;
+
+ return;
+}
+
+
+ARC_STATUS
+FwEnvironmentSetChecksum (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the environment area checksum.
+
+ This must ONLY be called from FwEnvironmentStore, which does the
+ required block erase & storage of the environment variable area.
+
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ ESUCCESS if the checksum was written OK.
+ EIO otherwise.
+
+--*/
+
+{
+ PUCHAR NvChars;
+ PNV_CONFIGURATION NvConfiguration;
+ ULONG Index;
+ ULONG Checksum;
+
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
+
+ //
+ // Form checksum from NVRAM data.
+ //
+
+ Checksum = 0;
+ NvChars = (PUCHAR)&NvConfiguration->Environment[0];
+
+ FwROMSetARCDataToReadMode();
+
+ for ( Index = 0 ; Index < LENGTH_OF_ENVIRONMENT; Index++ ) {
+ Checksum += HalpReadNVByte( NvChars++ );
+ }
+
+ //
+ // Write environment checksum.
+ //
+
+ if ((FwROMByteWrite(&NvConfiguration->Checksum2[0],
+ (UCHAR)(Checksum & 0xFF)) != ESUCCESS) ||
+ (FwROMByteWrite(&NvConfiguration->Checksum2[1],
+ (UCHAR)((Checksum >> 8) & 0xFF)) != ESUCCESS) ||
+ (FwROMByteWrite(&NvConfiguration->Checksum2[2],
+ (UCHAR)((Checksum >> 16) & 0xFF)) != ESUCCESS) ||
+ (FwROMByteWrite(&NvConfiguration->Checksum2[3],
+ (UCHAR)(Checksum >> 24)) != ESUCCESS)) {
+ return EIO;
+ } else {
+ return ESUCCESS;
+ }
+}
+
+
+PCHAR
+FwGetEnvironmentVariable (
+ IN PCHAR Variable
+ )
+
+/*++
+
+Routine Description:
+
+ This routine searches (not case sensitive) the non-volatile ram for
+ Variable, and if found returns a pointer to a zero terminated string that
+ contains the value, otherwise a NULL pointer is returned.
+
+ If the variable specified by Variable is protected, we get the information
+ from special global variables. See also the jnsetset.c and jxboot.c
+ modules.
+
+Arguments:
+
+ Variable - Supplies a zero terminated string containing an environment
+ variable.
+
+Return Value:
+
+ If successful, returns a zero terminated string that is the value of
+ Variable, otherwise NULL is returned.
+
+--*/
+
+{
+ CHAR TempString[MAXIMUM_ENVIRONMENT_VALUE];
+ PNV_CONFIGURATION NvConfiguration;
+ ULONG VariableIndex;
+ ULONG ValueIndex;
+ ULONG Outdex;
+ EXTENDED_SYSTEM_INFORMATION SystemInfo;
+
+ //
+ // If Variable is protected, create string and return
+ //
+
+ if (EnvironmentVariableIsProtected(Variable)) {
+
+ //
+ // Convert environment variable to uppercase.
+ //
+
+ Outdex = 0;
+ TempString[0] = 0;
+ while ((*Variable != 0) && (Outdex < MAXIMUM_ENVIRONMENT_VALUE)) {
+ TempString[Outdex] =
+ (((*Variable >= 'a') && (*Variable <= 'z')) ?
+ (*Variable - 'a' + 'A') : *Variable);
+ Outdex++;
+ Variable++;
+ }
+
+ if (Outdex == MAXIMUM_ENVIRONMENT_VALUE) {
+ // Something is very wrong!
+ return NULL;
+ }
+
+ TempString[Outdex] = 0;
+
+ FwReturnExtendedSystemInformation(&SystemInfo);
+
+
+ // Hack - I should be a static list of protected
+ // environment variables.
+
+ if (strstr(TempString, "PHYSICALADDRESSBITS")) {
+ sprintf(OutputString, "PHYSICALADDRESSBITS=%d",
+ SystemInfo.NumberOfPhysicalAddressBits);
+ return OutputString;
+ } else if (strstr(TempString, "MAXIMUMADDRESSSPACENUMBER")) {
+ sprintf(OutputString, "MAXIMUMADDRESSSPACENUMBER=%d",
+ SystemInfo.MaximumAddressSpaceNumber);
+ return OutputString;
+ } else if (strstr(TempString, "SYSTEMSERIALNUMBER")) {
+ sprintf(OutputString, "SYSTEMSERIALNUMBER=%s",
+ SystemInfo.SystemSerialNumber);
+ return OutputString;
+ } else if (strstr(TempString, "CYCLECOUNTERPERIOD")) {
+ sprintf(OutputString, "CYCLECOUNTERPERIOD=%d",
+ SystemInfo.ProcessorCycleCounterPeriod);
+ return OutputString;
+ } else if (strstr(TempString, "PROCESSORPAGESIZE")) {
+ sprintf(OutputString, "PROCESSORPAGESIZE=%d",
+ SystemInfo.ProcessorPageSize);
+ return OutputString;
+ } else {
+ // The requestion environment variable is supposed to
+ // be a protected one, so if we get to here then there
+ // is some internal error in the firmware. Error return.
+ return NULL;
+ }
+ }
+
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
+
+ //
+ // If checksum is wrong, or the variable can not be found, return NULL.
+ //
+
+ if ((JzEnvironmentCheckChecksum() != ESUCCESS) ||
+ (FwFindEnvironmentVariable(Variable, &VariableIndex, &ValueIndex) != ESUCCESS)) {
+ return NULL;
+ }
+
+ //
+ // Copy value to an output string, break on zero terminator or string max.
+ //
+
+ for ( Outdex = 0 ; Outdex < (MAXIMUM_ENVIRONMENT_VALUE - 1) ; Outdex++ ) {
+ if (HalpReadNVByte(&NvConfiguration->Environment[ValueIndex])
+ == 0) {
+ break;
+ }
+ OutputString[Outdex] =
+ HalpReadNVByte( &NvConfiguration->Environment[ValueIndex++] );
+ }
+
+ //
+ // Zero terminate string, and return.
+ //
+
+ OutputString[Outdex] = 0;
+ return OutputString;
+}
+
+PCHAR
+FwGetVolatileEnvironmentVariable (
+ IN PCHAR Variable
+ )
+
+/*++
+
+Routine Description:
+
+ This routine searches (not case sensitive) the volatile variables for
+ Variable, and if found returns a pointer to a zero terminated string that
+ contains the value, otherwise a NULL pointer is returned.
+
+ If the variable specified by Variable is protected, we get the information
+ from special global variables. See also the jnsetset.c and jxboot.c
+ modules.
+
+ This is used by the Setup utility to provide quick access to the
+ variables. It could completely take the place of
+ FwGetEnvironmentVariable() if there are no calls to it before
+ the volatile area is set up.
+
+Arguments:
+
+ Variable - Supplies a zero terminated string containing an environment
+ variable.
+
+Return Value:
+
+ If successful, returns a zero terminated string that is the value of
+ Variable, otherwise NULL is returned.
+
+--*/
+
+{
+ CHAR TempString[MAXIMUM_ENVIRONMENT_VALUE];
+ PUCHAR String;
+ ULONG Index;
+ ULONG ValueIndex;
+ ULONG VariableIndex;
+ ULONG Outdex;
+ EXTENDED_SYSTEM_INFORMATION SystemInfo;
+
+ //
+ // If Variable is protected, create string and return
+ //
+
+ if (EnvironmentVariableIsProtected(Variable)) {
+
+ //
+ // Convert environment variable to uppercase.
+ //
+
+ Outdex = 0;
+ TempString[0] = 0;
+ while ((*Variable != 0) && (Outdex < MAXIMUM_ENVIRONMENT_VALUE)) {
+ TempString[Outdex] =
+ (((*Variable >= 'a') && (*Variable <= 'z')) ?
+ (*Variable - 'a' + 'A') : *Variable);
+ Outdex++;
+ Variable++;
+ }
+
+ if (Outdex == MAXIMUM_ENVIRONMENT_VALUE) {
+ // Something is very wrong!
+ return NULL;
+ }
+
+ TempString[Outdex] = 0;
+
+ FwReturnExtendedSystemInformation(&SystemInfo);
+
+
+ // Hack - I should be a static list of protected
+ // environment variables.
+
+ if (strstr(TempString, "PHYSICALADDRESSBITS")) {
+ sprintf(OutputString, "PHYSICALADDRESSBITS=%d",
+ SystemInfo.NumberOfPhysicalAddressBits);
+ return OutputString;
+ } else if (strstr(TempString, "MAXIMUMADDRESSSPACENUMBER")) {
+ sprintf(OutputString, "MAXIMUMADDRESSSPACENUMBER=%d",
+ SystemInfo.MaximumAddressSpaceNumber);
+ return OutputString;
+ } else if (strstr(TempString, "SYSTEMSERIALNUMBER")) {
+ sprintf(OutputString, "SYSTEMSERIALNUMBER=%s",
+ SystemInfo.SystemSerialNumber);
+ return OutputString;
+ } else if (strstr(TempString, "CYCLECOUNTERPERIOD")) {
+ sprintf(OutputString, "CYCLECOUNTERPERIOD=%d",
+ SystemInfo.ProcessorCycleCounterPeriod);
+ return OutputString;
+ } else if (strstr(TempString, "PROCESSORPAGESIZE")) {
+ sprintf(OutputString, "PROCESSORPAGESIZE=%d",
+ SystemInfo.ProcessorPageSize);
+ return OutputString;
+ } else {
+ // The requestion environment variable is supposed to
+ // be a protected one, so if we get to here then there
+ // is some internal error in the firmware. Error return.
+ return NULL;
+ }
+ }
+
+ if (FwFindVolatileEnvironmentVariable(Variable,
+ &VariableIndex,
+ &ValueIndex) != ESUCCESS) {
+ return NULL;
+ }
+
+
+ //
+ // Copy value to an output string, break on zero terminator or string max.
+ //
+
+ for ( Outdex = 0 ; Outdex < (MAXIMUM_ENVIRONMENT_VALUE - 1) ; Outdex++ ) {
+ if (*(VolatileEnvironment + ValueIndex) == 0) {
+ break;
+ }
+ OutputString[Outdex] = *(VolatileEnvironment + ValueIndex++);
+ }
+
+ //
+ // Zero terminate string, and return.
+ //
+
+ OutputString[Outdex] = 0;
+ return OutputString;
+}
+
+
+#ifdef ALPHA
+
+ARC_STATUS
+FwSetEnvironmentVariable(
+ IN PCHAR Variable,
+ IN PCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets Variable (not case sensitive) to Value in the
+ Volatile and ROM areas.
+
+
+Arguments:
+
+ Variable - Supplies a zero terminated string containing an environment
+ variable.
+
+ Value - Supplies a zero terminated string containing an environment
+ variable value.
+
+Return Value:
+
+ Whatever is returned from FwCoreSetEnvironmentVariable. This should be:
+
+ Returns ESUCCESS if the set completed successfully, otherwise one of
+ the following error codes is returned.
+
+ ENOSPC No space in NVRAM for set operation.
+
+ EIO Invalid Checksum.
+
+ EACCES A protected environment variable cannot be changed.
+--*/
+
+{
+ return(FwCoreSetEnvironmentVariable(Variable, Value, TRUE));
+}
+
+#endif
+
+#ifdef ALPHA
+
+ARC_STATUS
+FwCoreSetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN PCHAR Value,
+ IN BOOLEAN UpdateTheROM
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets Variable (not case sensitive) to Value.
+
+ The MIPS version of this code modified the NVRAM directly.
+
+ Alpha/Jensen has a Flash ROM with a much slower write algorithm.
+ This function is therefore used in two ways:
+ a) By the ARC SetEnvironmentVariable function, to modify the Volatile
+ area and then the PROM configuration block.
+ b) By the setup utility, to modify just the Volatile area. The ROM
+ is updated upon exit from Setup.
+
+ This checks to see if the variable is protected.
+ If so, an error return is taken.
+
+Arguments:
+
+ Variable - Supplies a zero terminated string containing an environment
+ variable.
+
+ Value - Supplies a zero terminated string containing an environment
+ variable value.
+
+ UpdateTheROM - TRUE = update the Volatile area and the ROM.
+ FALSE = update the Volatile area only.
+
+Return Value:
+
+ Returns ESUCCESS if the set completed successfully, otherwise one of
+ the following error codes is returned.
+
+ ENOSPC No space in NVRAM for set operation.
+
+ EIO Invalid Checksum.
+
+ EACCES A protected environment variable cannot be changed.
+--*/
+
+{
+ ULONG VariableIndex;
+ ULONG ValueIndex;
+ ULONG TopOfEnvironment;
+ PCHAR String;
+ PUCHAR VChars;
+ ULONG Count;
+ CHAR Char;
+
+ //
+ // If checksum is wrong, return EIO;
+ //
+
+ if (UpdateTheROM && (JzEnvironmentCheckChecksum() != ESUCCESS)) {
+ return EIO;
+ }
+
+
+ //
+ // If the environment variable is protected, return EACCES.
+ //
+
+ if (EnvironmentVariableIsProtected(Variable)) {
+ return EACCES;
+ }
+
+ VChars = VolatileEnvironment;
+
+ //
+ // Determine the top of the environment space by looking for the first
+ // non-null character from the top.
+ //
+
+ TopOfEnvironment = LENGTH_OF_ENVIRONMENT - 1;
+
+ while (VChars[--TopOfEnvironment] == 0) {
+ if (TopOfEnvironment == 0) {
+ break;
+ }
+ }
+
+ //
+ // Adjust TopOfEnvironment to the first new character, unless environment
+ // space is empty.
+ //
+
+ if (TopOfEnvironment != 0) {
+ TopOfEnvironment += 2;
+ }
+
+ //
+ // Check to see if the variable already has a value.
+ //
+
+ Count = LENGTH_OF_ENVIRONMENT - TopOfEnvironment;
+
+ if (FwFindVolatileEnvironmentVariable(Variable,
+ &VariableIndex,
+ &ValueIndex) == ESUCCESS) {
+
+ //
+ // Count free space, starting with the free area at the top and adding
+ // the old variable value.
+ //
+
+ for ( String = VChars + ValueIndex ;
+ *String != 0 ;
+ String++ ) {
+ Count++;
+ }
+
+ //
+ // Determine if free area is large enough to handle new value, if not
+ // return error.
+ //
+
+ for ( String = Value ; *String != 0 ; String++ ) {
+ if (Count-- == 0) {
+ return ENOSPC;
+ }
+ }
+
+ //
+ // Move ValueIndex to the end of the value and compress strings.
+ //
+
+ while(VChars[ValueIndex++] != 0) {
+ }
+
+ while (ValueIndex < TopOfEnvironment ) {
+ VChars[VariableIndex++] = VChars[ValueIndex++];
+ }
+
+ //
+ // Adjust new top of environment.
+ //
+
+ TopOfEnvironment = VariableIndex;
+
+ //
+ // Zero to the end.
+ //
+
+ while (VariableIndex < LENGTH_OF_ENVIRONMENT) {
+ VChars[VariableIndex++] = 0;
+ }
+
+ //
+ // Variable is new.
+ //
+
+ } else {
+
+ //
+ // Determine if free area is large enough to handle new value, if not
+ // return error.
+ //
+
+ for ( String = Value ; *String != 0 ; String++ ) {
+ if (Count-- == 0) {
+ return ENOSPC;
+ }
+ }
+
+ }
+
+ //
+ // If Value is not zero, write new variable and value.
+ //
+
+ if (*Value != 0) {
+
+ //
+ // Write new variable, converting to upper case.
+ //
+
+ while (*Variable != 0) {
+ VChars[TopOfEnvironment++] =
+ ((*Variable >= 'a') && (*Variable <= 'z') ? (*Variable - 'a' + 'A') : *Variable);
+ Variable++;
+ }
+
+ //
+ // Write equal sign.
+ //
+
+ VChars[TopOfEnvironment++] = '=';
+
+ //
+ // Write new value.
+ //
+
+ while (*Value != 0) {
+ VChars[TopOfEnvironment++] = *Value++;
+ }
+ }
+
+
+ if (UpdateTheROM) {
+
+ //
+ // Now update the Jensen configuration/environment PROM block,
+ // including the appropriate checksums.
+ //
+
+ return FwSaveConfiguration();
+
+ } else {
+
+ return(ESUCCESS);
+
+ }
+
+}
+
+#endif
+
+ARC_STATUS
+FwFindEnvironmentVariable (
+ IN PCHAR Variable,
+ OUT PULONG VariableIndex,
+ OUT PULONG ValueIndex
+ )
+
+/*++
+
+Routine Description:
+
+ This routine searches (not case sensitive) the non-volatile ram for
+ Variable.
+
+
+Arguments:
+
+ Variable - Supplies a zero terminated string containing an environment
+ variable.
+
+Return Value:
+
+ If successful, returns ESUCCESS, otherwise returns ENOENT.
+
+--*/
+
+{
+ PNV_CONFIGURATION NvConfiguration;
+ PUCHAR String;
+ PUCHAR Environment;
+ ULONG Index;
+
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
+
+ //
+ // If Variable is null, return immediately.
+ //
+
+ if (*Variable == 0) {
+ return ENOENT;
+ }
+
+ Environment = NvConfiguration->Environment;
+ Index = 0;
+
+ while (TRUE) {
+
+ //
+ // Set string to beginning of Variable.
+ //
+
+ String = Variable;
+ *VariableIndex = Index;
+
+ //
+ // Search until the end of NVRAM.
+ //
+
+ while ( Index < LENGTH_OF_ENVIRONMENT ) {
+
+ //
+ // Convert to uppercase and break if mismatch.
+ //
+
+ if ( HalpReadNVByte( &Environment[Index] ) !=
+ ((*String >= 'a') &&
+ (*String <= 'z') ?
+ (*String - 'a' + 'A') : *String) ) {
+ break;
+ }
+
+ String++;
+ Index++;
+ }
+
+ //
+ // Check to see if we're at the end of the string and the variable,
+ // which means a match.
+ //
+
+ if ((*String == 0) && (HalpReadNVByte( &Environment[Index] ) == '=')) {
+ *ValueIndex = ++Index;
+ return ESUCCESS;
+ }
+
+ //
+ // Move index to the start of the next variable.
+ //
+
+ while (HalpReadNVByte( &Environment[Index++] ) != 0) {
+ if (Index >= LENGTH_OF_ENVIRONMENT) {
+ return ENOENT;
+ }
+ }
+ }
+}
+
+
+ARC_STATUS
+FwFindVolatileEnvironmentVariable (
+ IN PCHAR Variable,
+ OUT PULONG VariableIndex,
+ OUT PULONG ValueIndex
+ )
+
+/*++
+
+Routine Description:
+
+ This routine searches (not case sensitive) the Volatile area for
+ Variable.
+
+
+Arguments:
+
+ Variable - Supplies a zero terminated string containing an environment
+ variable.
+
+Return Value:
+
+ If successful, returns ESUCCESS, otherwise returns ENOENT.
+
+--*/
+
+{
+ PUCHAR String;
+ ULONG Index;
+
+ //
+ // If Variable is null, return immediately.
+ //
+
+ if (*Variable == 0) {
+ return ENOENT;
+ }
+
+ Index = 0;
+
+ while (TRUE) {
+
+ //
+ // Set string to beginning of Variable.
+ //
+
+ String = Variable;
+ *VariableIndex = Index;
+
+ //
+ // Search until the end of the volatile environment.
+ //
+
+ while (Index < LENGTH_OF_ENVIRONMENT) {
+
+ //
+ // Convert to uppercase and break if mismatch.
+ //
+
+ if (*(VolatileEnvironment + Index) !=
+ ((*String >= 'a') &&
+ (*String <= 'z') ?
+ (*String - 'a' + 'A') : *String) ) {
+ break;
+ }
+
+ String++;
+ Index++;
+ }
+
+ //
+ // Check to see if we are at the end of the string and the variable,
+ // which means a match.
+ //
+
+ if ((*String == 0) && (*(VolatileEnvironment + Index) == '=')) {
+ *ValueIndex = ++Index;
+ return ESUCCESS;
+ }
+
+ //
+ // Return if we are at the end of the Volatile Environment.
+ //
+
+ if (Index >= LENGTH_OF_ENVIRONMENT) {
+ return ENOENT;
+ }
+
+ //
+ // Move index to the start of the next variable.
+ //
+
+ while (*(VolatileEnvironment + Index++) != 0) {
+ if (Index >= LENGTH_OF_ENVIRONMENT) {
+ return ENOENT;
+ }
+ }
+ }
+}
+
+
+PCHAR
+FwEnvironmentLoad (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine loads the entire environment into the volatile environment
+ area.
+
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the checksum is good, a pointer to the environment in returned,
+ otherwise NULL is returned.
+
+--*/
+
+{
+ ULONG Index;
+ PUCHAR NvChars;
+ PUCHAR VChars;
+ PNV_CONFIGURATION NvConfiguration;
+
+ if (JzEnvironmentCheckChecksum() == ESUCCESS) {
+
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_CONFIGURATION;
+
+ //
+ // Copy the data into the volatile area.
+ //
+
+ NvChars = (PUCHAR)&NvConfiguration->Environment[0];
+ VChars = VolatileEnvironment;
+
+ for ( Index = 0 ;
+ Index < LENGTH_OF_ENVIRONMENT;
+ Index++ ) {
+ *VChars++ = HalpReadNVByte( NvChars++ );
+ }
+
+ return (PCHAR)VolatileEnvironment;
+ } else {
+ return NULL;
+ }
+
+}
+
+BOOLEAN
+EnvironmentVariableIsProtected (
+ IN PCHAR Variable
+ )
+/*++
+
+Routine Description:
+
+ Some environment variables are not allowed to be modified by the user.
+ This function checks to see if the argument is such a variable.
+
+Arguments:
+
+ Variable - A zero-terminated string containing an environment variable
+ name.
+
+Return Value:
+
+ TRUE if the environment variable exists and is protected.
+ FALSE if the environment variables does not exist, or is
+ not protected, or if an error occurred.
+
+--*/
+{
+ CHAR TempString[MAXIMUM_ENVIRONMENT_VALUE];
+ ULONG Index;
+
+ // Convert environment variable to uppercase.
+ Index = 0;
+ TempString[0] = 0;
+ while ((*Variable != 0) && (Index < MAXIMUM_ENVIRONMENT_VALUE)) {
+ TempString[Index] =
+ (((*Variable >= 'a') && (*Variable <= 'z')) ?
+ (*Variable - 'a' + 'A') : *Variable);
+ Index++;
+ Variable++;
+ }
+
+ // Check for string-too-long
+ if (Index == MAXIMUM_ENVIRONMENT_VALUE) {
+ return FALSE;
+ }
+
+ TempString[Index] = 0;
+
+ // Check whether this is a protected variable.
+ if ((strstr(TempString, "PHYSICALADDRESSBITS")) ||
+ (strstr(TempString, "MAXIMUMADDRESSSPACENUMBER")) ||
+ (strstr(TempString, "SYSTEMSERIALNUMBER")) ||
+ (strstr(TempString, "CYCLECOUNTERPERIOD")) ||
+ (strstr(TempString, "PROCESSORPAGESIZE"))) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
diff --git a/private/ntos/fw/alpha/jxfboot.c b/private/ntos/fw/alpha/jxfboot.c
new file mode 100644
index 000000000..039b56ee7
--- /dev/null
+++ b/private/ntos/fw/alpha/jxfboot.c
@@ -0,0 +1,2273 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ jxfboot.c
+
+Abstract:
+
+ This module implements the floppy disk boot driver for the Jazz system.
+
+Author:
+
+ Darryl E. Havens (darrylh) 28-Aug-1989
+
+Environment:
+
+ Kernel mode only, raised IRQL, generally self-contained.
+
+
+Revision History:
+
+ 31-August-1992 John DeRosa [DEC]
+
+ Made Alpha/Jensen modifications. This file is now Alpha-specific.
+
+--*/
+
+#include "fwp.h"
+#include "jnsnprom.h"
+#include "ntdddisk.h"
+#include "flo_data.h"
+#include "xxstring.h"
+
+//
+// Define local static data.
+//
+
+UCHAR DebugByte[8];
+ULONG MotorStatus;
+PDRIVE_MEDIA_CONSTANTS CurrentDriveMediaConstants;
+
+//
+// Define timeout constants.
+//
+
+#define MICROSECONDS_10 10
+#define MICROSECONDS_20 20
+#define MICROSECONDS_250 250
+#define MICROSECONDS_500 500
+#define MILLISECONDS_15 (15 * 1000)
+#define MILLISECONDS_30 (30 * 1000)
+#define MILLISECONDS_500 (500 * 1000)
+#define SECONDS_2 (2 * 1000 * 1000)
+#define FW_FLOPPY_TIMEOUT 2
+
+//
+// Define the number of times an operation is retried before it is considered
+// to be a hard error.
+//
+
+#define RETRY_COUNT 8
+
+//
+// Define the MINIMUM macro.
+//
+
+#define MINIMUM( x, y ) ( x <= y ? x : y )
+
+//
+// Define floppy device register structure.
+//
+
+typedef struct _FLOPPY_REGISTERS {
+ UCHAR StatusRegisterA;
+ UCHAR StatusRegisterB;
+ UCHAR DigitalOutput;
+ UCHAR Reserved1;
+ union {
+ UCHAR MainStatus;
+ UCHAR DataRateSelect;
+ } MsrDsr;
+ UCHAR Fifo;
+ UCHAR Reserved2;
+ union {
+ UCHAR DigitalInput;
+ UCHAR ConfigurationControl;
+ } DirCcr;
+} FLOPPY_REGISTERS, *PFLOPPY_REGISTERS;
+
+//
+// Define pointer to the floppy registers.
+//
+
+#define FLOPPY_CONTROL ((volatile PFLOPPY_REGISTERS)FLOPPY_VIRTUAL_BASE)
+
+
+
+//
+// Define bits in some of the floppy registers. The existing Microsoft
+// code uses constants (e.g. 0xC0) for register masking. These defines
+// will be used in Digital Equipment Corporation code.
+//
+
+#define FLOPPY_SRA_INTPENDING 0x80
+#define FLOPPY_MSR_DRV0BUSY 0x1
+#define FLOPPY_MSR_DRV1BUSY 0x2
+#define FLOPPY_MSR_CMDBUSY 0x10
+#define FLOPPY_MSR_NONDMA 0x20
+#define FLOPPY_MSR_DIO 0x40
+#define FLOPPY_MSR_RQM 0x80
+
+ARC_STATUS
+FloppyClose (
+ IN ULONG FileId
+ );
+
+ARC_STATUS
+FloppyMount (
+ IN PCHAR MountPath,
+ IN MOUNT_OPERATION Operation
+ );
+
+ARC_STATUS
+FloppyOpen (
+ IN PCHAR OpenPath,
+ IN OPEN_MODE OpenMode,
+ OUT PULONG FileId
+ );
+
+ARC_STATUS
+FloppyRead (
+ IN ULONG FileId,
+ IN PVOID Buffer,
+ IN ULONG Length,
+ OUT PULONG Count
+ );
+
+ARC_STATUS
+FloppyGetReadStatus (
+ IN ULONG FileId
+ );
+
+ARC_STATUS
+FloppySeek (
+ IN ULONG FileId,
+ IN PLARGE_INTEGER Offset,
+ IN SEEK_MODE SeekMode
+ );
+
+ARC_STATUS
+FloppyWrite (
+ IN ULONG FileId,
+ IN PVOID Buffer,
+ IN ULONG Length,
+ OUT PULONG Count
+ );
+
+ARC_STATUS
+FloppyGetFileInformation (
+ IN ULONG FileId,
+ OUT PFILE_INFORMATION Finfo
+ );
+
+ARC_STATUS
+FloppyBootIO(
+ IN PMDL MdlAddress,
+ IN ULONG StartingBlock,
+ IN ULONG FileId,
+ IN BOOLEAN ReadWrite
+ );
+
+VOID
+ClearFloppyFifo (
+ IN VOID
+ );
+
+ULONG
+ReadFloppyFifo (
+ IN PUCHAR Buffer
+ );
+
+VOID
+WriteFloppyFifo(
+ IN PUCHAR Buffer,
+ IN ULONG Size
+ );
+
+//
+// Declare and Initialize the floppy disk device entry table.
+//
+
+BL_DEVICE_ENTRY_TABLE FloppyEntryTable = {
+ FloppyClose,
+ FloppyMount,
+ FloppyOpen,
+ FloppyRead,
+ FloppyGetReadStatus,
+ FloppySeek,
+ FloppyWrite,
+ FloppyGetFileInformation,
+ (PARC_SET_FILE_INFO_ROUTINE)NULL
+ };
+
+//
+// Define prototypes for all routines used by this module.
+//
+
+
+ARC_STATUS
+WaitForFloppyInterrupt(
+ ULONG Timeout
+ );
+
+ARC_STATUS
+FloppyBootClose(
+ );
+
+BOOLEAN
+Recalibrate (
+ UCHAR DriveNumber
+ );
+
+ VOID
+FloppyBootSetup(
+ VOID
+ );
+
+UCHAR
+ReceiveByte (
+ );
+
+BOOLEAN
+SendByte(
+ IN UCHAR SourceByte
+ );
+
+ARC_STATUS
+FloppyDetermineMediaType(
+ IN OUT PFLOPPY_CONTEXT FloppyContext,
+ OUT PMEDIA_TYPE mediaType
+ );
+
+ARC_STATUS
+FloppyDatarateSpecifyConfigure(
+ IN DRIVE_MEDIA_TYPE DriveMediaType,
+ IN UCHAR DriveNumber
+ );
+
+
+ARC_STATUS
+FloppyClose (
+ IN ULONG FileId
+ )
+
+/*++
+
+Routine Description:
+
+ This function closes the file table entry specified by the file id.
+
+Arguments:
+
+ FileId - Supplies the file table index.
+
+Return Value:
+
+ ESUCCESS is returned
+
+--*/
+
+{
+ FloppyBootClose();
+ BlFileTable[FileId].Flags.Open = 0;
+ return ESUCCESS;
+}
+
+ARC_STATUS
+FloppyMount (
+ IN PCHAR MountPath,
+ IN MOUNT_OPERATION Operation
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ return ESUCCESS;
+}
+
+ARC_STATUS
+FloppyOpen (
+ IN PCHAR OpenPath,
+ IN OPEN_MODE OpenMode,
+ IN OUT PULONG FileId
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ PCONFIGURATION_COMPONENT FloppyComponent, FloppyController;
+ UCHAR Data[sizeof(CM_PARTIAL_RESOURCE_LIST) +
+ sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * 8 +
+ sizeof(CM_FLOPPY_DEVICE_DATA)];
+ PCM_PARTIAL_RESOURCE_LIST List = (PCM_PARTIAL_RESOURCE_LIST)Data;
+ PCM_FLOPPY_DEVICE_DATA FloppyData;
+ ULONG DriveNumber;
+ ULONG Index;
+ ARC_STATUS ArcStatus;
+ CHAR TempBuffer[SECTOR_SIZE + 32];
+ PCHAR TempPointer;
+ ULONG Count;
+ UCHAR mediaDescriptor;
+ MEDIA_TYPE mediaType = Unknown;
+ DRIVE_MEDIA_TYPE driveMediaType;
+ ULONG DriveType;
+ ULONG ConfigDriveType;
+
+ //
+ // Get the drive number from the pathname.
+ //
+
+ if (JzGetPathMnemonicKey(OpenPath, "fdisk", &DriveNumber)) {
+ return ENODEV;
+ }
+
+ //
+ // If the ARC CDS data is invalid, default to 2.88MB floppy
+ //
+
+ BlFileTable[*FileId].u.FloppyContext.DriveType = DRIVE_TYPE_2880;
+
+ //
+ // Look in the configuration database for the floppy device data to
+ // determine the size of the floppy drive.
+ //
+
+ FloppyComponent = FwGetComponent(OpenPath);
+ if ((FloppyComponent != NULL) &&
+ (FloppyComponent->Type == FloppyDiskPeripheral)) {
+ if (FwGetConfigurationData(List, FloppyComponent) == ESUCCESS) {
+ FloppyData = (PCM_FLOPPY_DEVICE_DATA)&List->PartialDescriptors[List->Count];
+ if (strcmp(FloppyData->Size,"5.25")==0) {
+ BlFileTable[*FileId].u.FloppyContext.DriveType = DRIVE_TYPE_1200;
+ } else {
+ if (strcmp(FloppyData->Size,"3.5")==0) {
+ if (FloppyData->MaxDensity == 2880) {
+ BlFileTable[*FileId].u.FloppyContext.DriveType = DRIVE_TYPE_2880;
+ } else {
+ BlFileTable[*FileId].u.FloppyContext.DriveType = DRIVE_TYPE_1440;
+ }
+ }
+ }
+ }
+ }
+
+ ConfigDriveType = BlFileTable[*FileId].u.FloppyContext.DriveType;
+ BlFileTable[*FileId].u.FloppyContext.DiskId = DriveNumber;
+ BlFileTable[*FileId].Position.LowPart=0;
+ BlFileTable[*FileId].Position.HighPart=0;
+
+ //
+ // Enable the drive and start the motor via the DOR.
+ //
+
+ if (MotorStatus != DriveNumber) {
+ WRITE_PORT_UCHAR((PUCHAR)&FLOPPY_CONTROL->DigitalOutput,
+ ((0xc + DriveNumber) + (1 << (DriveNumber + 4))));
+ MotorStatus = DriveNumber;
+
+ //
+ // Wait for at least 500ms to ensure that the motor really is running.
+ //
+
+ FwStallExecution(MILLISECONDS_500);
+ }
+
+ //
+ // Determine the disk density.
+ //
+
+ ClearFloppyFifo();
+ ArcStatus = FloppyDetermineMediaType(&BlFileTable[*FileId].u.FloppyContext,
+ &mediaType);
+ if (ArcStatus == EIO) {
+
+ FloppyClose(*FileId);
+
+ //
+ // Reset the floppy, it seems to get in a bad state.
+ //
+
+ FloppyBootSetup();
+ return(ArcStatus);
+
+ } else if (ArcStatus != ESUCCESS) {
+
+ //
+ // The floppy was not readable, so try next lowest floppy type.
+ //
+
+ DriveType = BlFileTable[*FileId].u.FloppyContext.DriveType;
+
+ if (DriveType == DRIVE_TYPE_2880) {
+ BlFileTable[*FileId].u.FloppyContext.DriveType = DRIVE_TYPE_1440;
+ } else if (DriveType == DRIVE_TYPE_1440) {
+ BlFileTable[*FileId].u.FloppyContext.DriveType = DRIVE_TYPE_1200;
+ }
+
+ ArcStatus = FloppyDetermineMediaType(&BlFileTable[*FileId].u.FloppyContext,
+ &mediaType);
+
+ if (ArcStatus != ESUCCESS) {
+// FwPrint("Unrecognized floppy format\r\n");
+ FloppyClose(*FileId);
+ return(ArcStatus);
+ }
+ }
+
+ //
+ // Read the first sector to get the media descriptor byte.
+ //
+
+ TempPointer = (PVOID) ((ULONG) (TempBuffer + KeGetDcacheFillSize() - 1)
+ & ~(KeGetDcacheFillSize() - 1));
+ ArcStatus = FloppyRead(*FileId, TempPointer, SECTOR_SIZE, &Count);
+
+ if (ArcStatus != ESUCCESS) {
+// FwPrint("Error opening floppy\r\n");
+ FloppyClose(*FileId);
+ return(ArcStatus);
+ }
+
+ //
+ // Check the media descriptor byte to verify that we have the right
+ // drive and media type.
+ //
+
+ DriveType = BlFileTable[*FileId].u.FloppyContext.DriveType;
+ mediaDescriptor = *( TempPointer + MEDIA_DESCRIPTOR_OFFSET );
+
+ switch ( mediaDescriptor ) {
+
+ case MEDIA_DESCRIPTOR_160K:
+ mediaType = F5_160_512;
+ DriveType = DRIVE_TYPE_1200;
+ break;
+
+ case MEDIA_DESCRIPTOR_180K:
+ mediaType = F5_180_512;
+ DriveType = DRIVE_TYPE_1200;
+ break;
+
+ case MEDIA_DESCRIPTOR_320K:
+ mediaType = F5_320_512;
+ DriveType = DRIVE_TYPE_1200;
+ break;
+
+ case MEDIA_DESCRIPTOR_360K:
+ mediaType = F5_360_512;
+ DriveType = DRIVE_TYPE_1200;
+ break;
+
+ case MEDIA_DESCRIPTOR_720K_OR_1220K:
+
+ //
+ // The following code tries to take care of the case when the floppy
+ // is really a 5 1/4" drive but the firmware thinks its 3 1/2". A
+ // 1.2 MByte floppy can be read with the 1.44 MByte parameters, but
+ // the descriptor byte will be MEDIA_DESCRIPTOR_720K_OR_1220K. Check
+ // if the parameters are really for 720 K, otherwise default to
+ // 1.2 MByte.
+ //
+
+ if ((DriveType == DRIVE_TYPE_1440) &&
+ (BlFileTable[*FileId].u.FloppyContext.SectorsPerTrack == 9)) {
+ mediaType = F3_720_512;
+ } else {
+ mediaType = F5_1Pt2_512;
+ DriveType = DRIVE_TYPE_1200;
+ }
+ break;
+
+
+ case MEDIA_DESCRIPTOR_1440K_OR_2880K:
+ default:
+
+ //
+ // FloppyDetermineMediaType did the right thing for this case,
+ // so no additional verification is needed.
+ //
+
+ break;
+ }
+
+
+ if ( mediaType != 0 ) {
+
+ //
+ // Find the constants for this media type.
+ //
+
+ driveMediaType = DriveMediaLimits[DriveType].HighestDriveMediaType;
+ while ( ( DriveMediaConstants[driveMediaType].MediaType != mediaType ) &&
+ ( driveMediaType > DriveMediaLimits[DriveType].LowestDriveMediaType ) ) {
+
+ driveMediaType--;
+ }
+
+ //
+ // Set the sectors per track and the drive type in the floppy
+ // context record.
+ //
+
+ BlFileTable[*FileId].u.FloppyContext.SectorsPerTrack =
+ DriveMediaConstants[driveMediaType].SectorsPerTrack;
+ BlFileTable[*FileId].u.FloppyContext.DriveType = DriveType;
+ }
+
+ //
+ // If the floppy drive type has changed, update the configuration database
+ // with the correct drive type.
+ //
+
+ if (DriveType != ConfigDriveType) {
+
+ switch (DriveType) {
+
+ case DRIVE_TYPE_1200:
+
+ strcpy(FloppyData->Size,"5.25");
+ FloppyData->MaxDensity = 1200;
+ break;
+
+ case DRIVE_TYPE_1440:
+
+ strcpy(FloppyData->Size,"3.5");
+ FloppyData->MaxDensity = 1440;
+ break;
+
+ default:
+
+ strcpy(FloppyData->Size,"3.5");
+ FloppyData->MaxDensity = 2880;
+ break;
+ }
+
+ //
+ // Get a pointer to the floppy controller component.
+ //
+
+ if ((FloppyController = FwGetParent(FloppyComponent)) != NULL) {
+
+ //
+ // Delete the old entry, note that this does not actually delete the
+ // data in the database, it only changes the pointers, so that the
+ // AddChild call can still use the old component data structure.
+ //
+
+ if (FwDeleteComponent(FloppyComponent) == ESUCCESS) {
+
+ //
+ // Add back the modified floppy structure.
+ //
+
+ FwAddChild(FloppyController, FloppyComponent, List);
+ }
+ }
+ }
+
+ return ESUCCESS;
+}
+
+ARC_STATUS
+FloppyRead (
+ IN ULONG FileId,
+ IN PVOID Buffer,
+ IN ULONG Length,
+ OUT PULONG Count
+ )
+
+/*++
+
+Routine Description:
+
+ This function reads data from the floppy starting at the position
+ specified in the file table.
+
+
+Arguments:
+
+ FileId - Supplies the file table index.
+
+ Buffer - Supplies a poiner to the buffer that receives the data
+ read.
+
+ Length - Supplies the number of bytes to be read.
+
+ Count - Supplies a pointer to a variable that receives the number of
+ bytes actually read.
+
+Return Value:
+
+
+ The read completion status is returned.
+
+--*/
+
+{
+
+ ARC_STATUS ArcStatus;
+ ULONG FrameNumber;
+ ULONG Index;
+ ULONG Limit;
+ PMDL MdlAddress;
+ UCHAR MdlBuffer[sizeof(MDL) + ((64 / 4) + 1) * sizeof(ULONG)];
+ ULONG NumberOfPages;
+ ULONG Offset;
+ PULONG PageFrame;
+ ULONG Position;
+ CHAR TempBuffer[SECTOR_SIZE + 32];
+ PCHAR TempPointer;
+
+ //
+ // If the requested size of the transfer is zero return ESUCCESS
+ //
+ if (Length==0) {
+ return ESUCCESS;
+ }
+ //
+ // If the current position is not at a sector boundary , then
+ // read the first and/or last sector separately and copy the data.
+ //
+
+ Offset = BlFileTable[FileId].Position.LowPart & (SECTOR_SIZE - 1);
+ if (Offset != 0) {
+ //
+ // Adjust position to the sector boundary, align the transfer address
+ // and read that first sector.
+ //
+ BlFileTable[FileId].Position.LowPart -= Offset;
+ TempPointer = (PVOID) ((ULONG) (TempBuffer + KeGetDcacheFillSize() - 1)
+ & ~(KeGetDcacheFillSize() - 1));
+
+ ArcStatus = FloppyRead(FileId, TempPointer, SECTOR_SIZE, Count);
+
+ //
+ // If the transfer was not successful, then reset the position
+ // and return the completion status.
+ //
+ if (ArcStatus != ESUCCESS) {
+ BlFileTable[FileId].Position.LowPart += Offset;
+ return ArcStatus;
+ }
+
+ //
+ // If the length of read is less than the number of bytes from
+ // the offset to the end of the sector, then copy only the number
+ // of bytes required to fulfil the request. Otherwise copy to the end
+ // of the sector and, read the remaining data.
+ //
+
+ if ((SECTOR_SIZE - Offset) > Length) {
+ Limit = Offset + Length;
+ } else {
+ Limit = SECTOR_SIZE;
+ }
+
+ //
+ // Copy the data to the specified buffer.
+ //
+ for (Index = Offset; Index < Limit; Index += 1) {
+ *((PCHAR)Buffer)++ = *(TempPointer + Index);
+ }
+
+ //
+ // Adjust the current position and
+ // Read the remaining part of the specified transfer.
+ //
+
+ BlFileTable[FileId].Position.LowPart -= SECTOR_SIZE-Limit;
+ Position = BlFileTable[FileId].Position.LowPart;
+ ArcStatus = FloppyRead(FileId,
+ Buffer,
+ Length - (Limit - Offset),
+ Count);
+
+ //
+ // If the transfer was not successful, then reset the device
+ // position and return the completion status.
+ //
+
+ if (ArcStatus != ESUCCESS) {
+ BlFileTable[FileId].Position.LowPart = Position;
+ return ArcStatus;
+ } else {
+ *Count = Length;
+ return ESUCCESS;
+ }
+ } else {
+ //
+ // if the size of requested data is not a multiple of the sector
+ // size then read the last sector separately.
+ //
+ if (Length & (SECTOR_SIZE - 1)) {
+ Position = BlFileTable[FileId].Position.LowPart;
+ ArcStatus = FloppyRead(FileId,
+ Buffer,
+ Length & (~(SECTOR_SIZE - 1)),
+ Count);
+
+ //
+ // If the transfer was not successful, then reset the device
+ // position and return the completion status.
+ //
+ if (ArcStatus != ESUCCESS) {
+ BlFileTable[FileId].Position.LowPart = Position;
+ return ArcStatus;
+ }
+
+ //
+ // Read the last sector and copy the requested data.
+ //
+ TempPointer = (PVOID) ((ULONG) (TempBuffer + KeGetDcacheFillSize() - 1)
+ & ~(KeGetDcacheFillSize() - 1));
+
+ ArcStatus = FloppyRead(FileId, TempPointer, SECTOR_SIZE, Count);
+
+ //
+ // If the transfer was not successful return the completion status.
+ //
+ if (ArcStatus != ESUCCESS) {
+ return ArcStatus;
+ }
+
+ //
+ // Copy the data to the specified buffer.
+ //
+ (PCHAR)Buffer += Length & (~(SECTOR_SIZE - 1));
+ Limit = Length & (SECTOR_SIZE - 1);
+ for (Index = 0; Index < Limit; Index += 1) {
+ *((PCHAR)Buffer)++ = *(TempPointer + Index);
+ }
+ BlFileTable[FileId].Position.LowPart -= SECTOR_SIZE - Limit;
+ *Count = Length;
+ return ESUCCESS;
+
+
+
+ } else {
+
+ //
+ // Build the memory descriptor list.
+ //
+
+ MdlAddress = (PMDL)&MdlBuffer[0];
+ MdlAddress->Next = NULL;
+ MdlAddress->Size = sizeof(MDL) +
+ ADDRESS_AND_SIZE_TO_SPAN_PAGES(Buffer, Length) * sizeof(ULONG);
+ MdlAddress->StartVa = (PVOID)PAGE_ALIGN(Buffer);
+ MdlAddress->ByteCount = Length;
+ MdlAddress->ByteOffset = BYTE_OFFSET(Buffer);
+ PageFrame = (PULONG)(MdlAddress + 1);
+ FrameNumber = (((ULONG)MdlAddress->StartVa) & 0x1fffffff) >> PAGE_SHIFT;
+ NumberOfPages = (MdlAddress->ByteCount +
+ MdlAddress->ByteOffset + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ for (Index = 0; Index < NumberOfPages; Index += 1) {
+ *PageFrame++ = FrameNumber++;
+ }
+
+ //
+ // Flush I/O buffers and read from the boot device.
+ //
+
+ HalFlushIoBuffers(MdlAddress, TRUE, TRUE);
+ ArcStatus = FloppyBootIO(MdlAddress,
+ BlFileTable[FileId].Position.LowPart >> SECTOR_SHIFT,
+ FileId,
+ FALSE);
+
+ if (ArcStatus == ESUCCESS) {
+ BlFileTable[FileId].Position.LowPart += Length;
+ *Count = Length;
+ return ESUCCESS;
+ } else {
+ *Count = 0;
+ return EIO;
+ }
+ }
+ }
+}
+
+ARC_STATUS
+FloppyWrite (
+ IN ULONG FileId,
+ IN PVOID Buffer,
+ IN ULONG Length,
+ OUT PULONG Count
+ )
+
+/*++
+
+Routine Description:
+
+ This function writes data to the floppy starting at the position
+ specified in the file table.
+
+
+Arguments:
+
+ FileId - Supplies the file table index.
+
+ Buffer - Supplies a poiner to the buffer that contains the data
+ to be written.
+
+ Length - Supplies the number of bytes to be writtes.
+
+ Count - Supplies a pointer to a variable that receives the number of
+ bytes actually written.
+
+Return Value:
+
+
+ The write completion status is returned.
+
+--*/
+
+{
+
+ ARC_STATUS ArcStatus;
+ ULONG FrameNumber;
+ ULONG Index;
+ ULONG Limit;
+ PMDL MdlAddress;
+ UCHAR MdlBuffer[sizeof(MDL) + ((64 / 4) + 1) * sizeof(ULONG)];
+ ULONG NumberOfPages;
+ ULONG Offset;
+ PULONG PageFrame;
+ ULONG Position;
+ CHAR TempBuffer[SECTOR_SIZE + 32];
+ PCHAR TempPointer;
+
+ //
+ // If the requested size of the transfer is zero return ESUCCESS
+ //
+ if (Length==0) {
+ return ESUCCESS;
+ }
+ //
+ // If the current position is not at a sector boundary , then
+ // read the first and/or last sector separately and copy the data.
+ //
+
+ Offset = BlFileTable[FileId].Position.LowPart & (SECTOR_SIZE - 1);
+ if (Offset != 0) {
+ //
+ // Adjust position to the sector boundary, align the transfer address
+ // and read that first sector.
+ //
+ BlFileTable[FileId].Position.LowPart -= Offset;
+ TempPointer = (PVOID) ((ULONG) (TempBuffer + KeGetDcacheFillSize() - 1)
+ & ~(KeGetDcacheFillSize() - 1));
+
+ ArcStatus = FloppyRead(FileId, TempPointer, SECTOR_SIZE, Count);
+
+ //
+ // If the transfer was not successful, then reset the position
+ // and return the completion status.
+ //
+ if (ArcStatus != ESUCCESS) {
+ BlFileTable[FileId].Position.LowPart += Offset;
+ return ArcStatus;
+ } else {
+ //
+ // Reset the position as it was before the read.
+ //
+ BlFileTable[FileId].Position.LowPart -= SECTOR_SIZE;
+ }
+
+ //
+ // If the length of write is less than the number of bytes from
+ // the offset to the end of the sector, then copy only the number
+ // of bytes required to fulfil the request. Otherwise copy to the end
+ // of the sector and, read the remaining data.
+ //
+
+ if ((SECTOR_SIZE - Offset) > Length) {
+ Limit = Offset + Length;
+ } else {
+ Limit = SECTOR_SIZE;
+ }
+
+ //
+ // Merge the data from the specified buffer.
+ //
+ for (Index = Offset; Index < Limit; Index += 1) {
+ *(TempPointer + Index) = *((PCHAR)Buffer)++;
+ }
+
+ //
+ // Write the modified sector.
+ //
+ ArcStatus = FloppyWrite(FileId, TempPointer, SECTOR_SIZE, Count);
+
+ if (ArcStatus != ESUCCESS) {
+ return ArcStatus;
+ }
+
+ //
+ // Adjust the current position and
+ // Write the remaining part of the specified transfer.
+ //
+
+ BlFileTable[FileId].Position.LowPart -= SECTOR_SIZE-Limit;
+ Position = BlFileTable[FileId].Position.LowPart;
+ ArcStatus = FloppyWrite(FileId,
+ Buffer,
+ Length - (Limit - Offset),
+ Count);
+
+ //
+ // If the transfer was not successful, then reset the device
+ // position and return the completion status.
+ //
+
+ if (ArcStatus != ESUCCESS) {
+ BlFileTable[FileId].Position.LowPart = Position;
+ return ArcStatus;
+ } else {
+ *Count = Length;
+ return ESUCCESS;
+ }
+ } else {
+ //
+ // if the size of requested data is not a multiple of the sector
+ // size then write the last sector separately.
+ //
+ if (Length & (SECTOR_SIZE - 1)) {
+
+ //
+ // Do the transfer of the complete sectors in the middle
+ //
+ Position = BlFileTable[FileId].Position.LowPart;
+ ArcStatus = FloppyWrite(FileId,
+ Buffer,
+ Length & (~(SECTOR_SIZE - 1)),
+ Count);
+
+ //
+ // If the transfer was not successful, then reset the device
+ // position and return the completion status.
+ //
+ if (ArcStatus != ESUCCESS) {
+ BlFileTable[FileId].Position.LowPart = Position;
+ return ArcStatus;
+ }
+
+ //
+ // Read the last sector and copy the requested data.
+ //
+ TempPointer = (PVOID) ((ULONG) (TempBuffer + KeGetDcacheFillSize() - 1)
+ & ~(KeGetDcacheFillSize() - 1));
+
+ ArcStatus = FloppyRead(FileId, TempPointer, SECTOR_SIZE, Count);
+
+ //
+ // If the transfer was not successful return the completion status.
+ //
+ if (ArcStatus != ESUCCESS) {
+ return ArcStatus;
+ }
+
+ //
+ // Copy the data to the specified buffer.
+ //
+ (PCHAR)Buffer += Length & (~(SECTOR_SIZE - 1));
+ Limit = Length & (SECTOR_SIZE - 1);
+ for (Index = 0; Index < Limit; Index += 1) {
+ *(TempPointer + Index) = *((PCHAR)Buffer)++;
+ }
+ //
+ // Adjust the position and write the data.
+ //
+ BlFileTable[FileId].Position.LowPart -= SECTOR_SIZE;
+ ArcStatus = FloppyWrite(FileId, TempPointer, SECTOR_SIZE, Count);
+
+ //
+ // Set the position for the requested transfer
+ //
+ BlFileTable[FileId].Position.LowPart -= SECTOR_SIZE - Limit;
+
+ *Count = Length;
+ return ArcStatus;
+
+ } else {
+
+ //
+ // Build the memory descriptor list.
+ //
+
+ MdlAddress = (PMDL)&MdlBuffer[0];
+ MdlAddress->Next = NULL;
+ MdlAddress->Size = sizeof(MDL) +
+ ADDRESS_AND_SIZE_TO_SPAN_PAGES(Buffer, Length) * sizeof(ULONG);
+ MdlAddress->StartVa = (PVOID)PAGE_ALIGN(Buffer);
+ MdlAddress->ByteCount = Length;
+ MdlAddress->ByteOffset = BYTE_OFFSET(Buffer);
+ PageFrame = (PULONG)(MdlAddress + 1);
+ FrameNumber = (((ULONG)MdlAddress->StartVa) & 0x1fffffff) >> PAGE_SHIFT;
+ NumberOfPages = (MdlAddress->ByteCount +
+ MdlAddress->ByteOffset + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ for (Index = 0; Index < NumberOfPages; Index += 1) {
+ *PageFrame++ = FrameNumber++;
+ }
+
+ //
+ // Flush I/O buffers and write to the boot device.
+ //
+
+ HalFlushIoBuffers(MdlAddress, FALSE, TRUE);
+ ArcStatus = FloppyBootIO(MdlAddress,
+ BlFileTable[FileId].Position.LowPart >> SECTOR_SHIFT,
+ FileId,
+ TRUE);
+
+ if (ArcStatus == ESUCCESS) {
+ BlFileTable[FileId].Position.LowPart += Length;
+ *Count = Length;
+ return ESUCCESS;
+ } else {
+ *Count = 0;
+ return EIO;
+ }
+ }
+ }
+}
+
+ARC_STATUS
+FloppyGetReadStatus (
+ IN ULONG FileId
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ return ESUCCESS;
+}
+
+ARC_STATUS
+FloppySeek (
+ IN ULONG FileId,
+ IN PLARGE_INTEGER Offset,
+ IN SEEK_MODE SeekMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function sets the device position to the specified offset for
+ the specified file id.
+
+Arguments:
+
+ FileId - Supplies the file table index.
+
+ Offset - Supplies to new device position.
+
+ SeekMode - Supplies the mode for the position.
+
+Return Value:
+
+ ESUCCESS is returned.
+
+--*/
+
+{
+
+ //
+ // Set the current device position as specifed by the seek mode.
+ //
+
+ if (SeekMode == SeekAbsolute) {
+ BlFileTable[FileId].Position.LowPart = Offset->LowPart;
+
+ } else if (SeekMode == SeekRelative) {
+ BlFileTable[FileId].Position.LowPart += Offset->LowPart;
+ }
+
+ return ESUCCESS;
+}
+
+ARC_STATUS
+FloppyGetFileInformation (
+ IN ULONG FileId,
+ OUT PFILE_INFORMATION Finfo
+ )
+
+/*++
+
+Routine Description:
+
+ This routine returns the floppy size.
+
+Arguments:
+
+ FileId - Supplies the file table index.
+
+ Finfo - Supplies a pointer to where the File Information is stored.
+
+Return Value:
+
+ ESUCCESS is returned.
+
+--*/
+
+{
+
+ RtlZeroMemory(Finfo, sizeof(FILE_INFORMATION));
+
+ switch (BlFileTable[FileId].u.FloppyContext.DriveType) {
+
+ case DRIVE_TYPE_1200: Finfo->EndingAddress.LowPart = 1200 * 1024;
+ break;
+ case DRIVE_TYPE_1440: Finfo->EndingAddress.LowPart = 1440 * 1024;
+ break;
+ case DRIVE_TYPE_2880: Finfo->EndingAddress.LowPart = 2880 * 1024;
+ break;
+
+ default : return EINVAL;
+ }
+
+ Finfo->CurrentPosition = BlFileTable[FileId].Position;
+ Finfo->Type = FloppyDiskPeripheral;
+ return ESUCCESS;
+}
+
+
+VOID
+FloppyBootSetup(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to initialize the floppy boot device before any
+ other floppy operations are attempted. This routine performs the following
+ operations to initialize the device:
+
+ o Clear the reset and DMA gate flags in the DOR
+ o Reset the floppy by writing the s/w reset in the DSR
+ o Set the program data rate in the CCR
+ o Issue a sense interrupt command and read the four statuses back
+ o Issue a configure command
+ o Issue a specify command
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG i,j;
+ //
+ // Begin by clearing the reset and DMA gate flags in the DOR.
+ //
+
+ WRITE_PORT_UCHAR((PUCHAR)&FLOPPY_CONTROL->DigitalOutput, 0x0c);
+ FwStallExecution(MICROSECONDS_500);
+
+ //
+ // Reset the floppy controller by setting the s/w reset bit in the DSR.
+ //
+
+ WRITE_PORT_UCHAR((PUCHAR)&FLOPPY_CONTROL->MsrDsr.DataRateSelect, 0x80);
+ FwStallExecution(MILLISECONDS_30);
+
+ //
+ // Set the data rate in the CCR.
+ //
+
+// WRITE_PORT_UCHAR(&FLOPPY_CONTROL->DirCcr.ConfigurationControl, 0);
+
+// if (FwWaitForDeviceInterrupt(1 << (FLOPPY_VECTOR - DEVICE_VECTORS - 1),
+// FW_FLOPPY_TIMEOUT)) {
+ if (WaitForFloppyInterrupt(FW_FLOPPY_TIMEOUT)) {
+// FwPrint("Floppy setup timeout\r\n");
+ return;
+ }
+
+ FwStallExecution(MICROSECONDS_20);
+
+
+ //
+ // Issue the sense interrupt command and read back the status and
+ // relative cylinder number from the controller. This is done for
+ // each of the four possible devices. Note that the output is always
+ // ignored.
+ //
+
+ for (i = j = 0; i <= 3; i++) {
+ SendByte(COMMND_SENSE_INTERRUPT);
+ DebugByte[j++] = ReceiveByte();
+ DebugByte[j++] = ReceiveByte();
+ }
+
+ //
+ // Issue the configuration command.
+ //
+
+ SendByte( COMMND_CONFIGURE ); // command
+ SendByte( 0x00 ); // required 0
+ SendByte( 0x58 ); // implied seeks, disable polling & threshold = 8
+ SendByte( 0x00 ); // precompensation track = 0
+
+ //
+ // Issue the specify command.
+ //
+
+ SendByte( COMMND_SPECIFY ); // command
+ SendByte( 0xdf ); // step rate time=d, head unload=f
+ SendByte( 0x03 ); // head load=1, DMA disabled
+
+ return;
+}
+
+VOID
+FloppyInitialize(
+ IN OUT PDRIVER_LOOKUP_ENTRY LookupTable,
+ IN ULONG Entries
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the FloppyDriver.
+
+Arguments:
+
+ LookupTable - Pointer to the driver lookup table where the pathnames
+ recognized by this driver will be stored.
+
+ Entries - Number of entries in the table.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PCONFIGURATION_COMPONENT FloppyComponent;
+ CHAR FloppyPath[32];
+ ULONG Drive;
+ //
+ // Set motor status to all motors stopped.
+ //
+
+ MotorStatus = MAXLONG;
+
+ FloppyBootSetup();
+
+ //
+ // Default to floppy 0 in case no configuration is present in the NVRAM
+ //
+ LookupTable->DevicePath = FW_FLOPPY_0_DEVICE;
+ LookupTable->DispatchTable = &FloppyEntryTable;
+
+ //
+ // Get the floppy configuration information.
+ //
+ FloppyComponent = FwGetComponent(FW_FLOPPY_0_DEVICE);
+ if ((FloppyComponent != NULL) &&
+ (FloppyComponent->Type == FloppyDiskPeripheral)) {
+
+ //
+ // Initialize the lookup table.
+ //
+
+ LookupTable->DevicePath = FW_FLOPPY_0_DEVICE;
+ LookupTable->DispatchTable = &FloppyEntryTable;
+ LookupTable++;
+
+ //
+ // Return if no more room in the lookup table.
+ //
+
+ if (Entries == 1) {
+ return;
+ }
+ }
+ FloppyComponent = FwGetComponent(FW_FLOPPY_1_DEVICE);
+ if ((FloppyComponent != NULL) &&
+ (FloppyComponent->Type == FloppyDiskPeripheral)) {
+
+ //
+ // Initialize the lookup table.
+ //
+ LookupTable->DevicePath = FW_FLOPPY_1_DEVICE;
+ LookupTable->DispatchTable = &FloppyEntryTable;
+ }
+}
+
+ARC_STATUS
+FloppyBootClose(
+ )
+
+/*++
+
+Routine Description:
+
+ This routine shuts down the floppy after the boot has taken place.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Normal, successful completion status.
+
+--*/
+
+{
+
+ //
+ // Turn the floppy drive's motor off and indicate that the
+ // motor has been shut off.
+ //
+
+ WRITE_PORT_UCHAR((PUCHAR)&FLOPPY_CONTROL->DigitalOutput, 0xc);
+ MotorStatus = MAXLONG;
+
+
+ return ESUCCESS;
+}
+
+ARC_STATUS
+FloppyBootIO (
+ IN PMDL Mdl,
+ IN ULONG StartingBlock,
+ IN ULONG FileId,
+ IN BOOLEAN ReadWrite
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads or writes blocks from the floppy into the buffer described by
+ the MDL. The size of the read is the number of bytes mapped by the MDL
+ and the blocks read start at StartingBlock.
+
+Arguments:
+
+ Mdl - Memory Descriptor List for buffer.
+
+ StartingBlock - Block to begin the read operation.
+
+ FileId - The file identifier of the floppy drive to access.
+
+ ReadWrite - Specifies the kind of transfer to be done
+ TRUE = WRITE
+ FALSE = READ
+
+Return Value:
+
+ The function value is the status of the operation.
+
+
+--*/
+
+{
+
+ UCHAR Cylinder;
+ UCHAR Head = 0;
+ UCHAR Sector;
+ UCHAR EndSector;
+ ULONG BlockCount;
+ ULONG TransferSize;
+ ULONG TransferedBytes;
+ ULONG i,j,k;
+ PUCHAR Buffer;
+ BOOLEAN Success;
+ ARC_STATUS Status = ESUCCESS;
+ UCHAR DriveNumber;
+ ULONG SectorsPerTrack;
+
+ DriveNumber = BlFileTable[FileId].u.FloppyContext.DiskId;
+ SectorsPerTrack = BlFileTable[FileId].u.FloppyContext.SectorsPerTrack;
+
+ //
+ // Enable the drive and start the motor via the DOR.
+ //
+
+ if (MotorStatus != DriveNumber) {
+ WRITE_PORT_UCHAR((PUCHAR)&FLOPPY_CONTROL->DigitalOutput,
+ ((0xc + DriveNumber) + (1 << (DriveNumber + 4))));
+ MotorStatus = DriveNumber;
+
+ //
+ // Wait for at least 500ms to ensure that the motor really is running.
+ //
+
+ FwStallExecution(MILLISECONDS_500);
+ }
+
+ //
+ // Get the number of blocks that need to be read in order to fulfill
+ // this request. Also set the base address of the caller's buffer.
+ //
+
+ Buffer = ((PUCHAR) Mdl->StartVa) + Mdl->ByteOffset;
+
+ //
+ // Get the parameters for the read command.
+ //
+
+ Cylinder = StartingBlock / (SectorsPerTrack * 2);
+ Sector = (StartingBlock % SectorsPerTrack) + 1;
+ Head = (StartingBlock / SectorsPerTrack) % 2;
+
+ ClearFloppyFifo();
+
+ //
+ // Loop reading blocks from the device until the request has been
+ // satisfied.
+ //
+
+ for (BlockCount = Mdl->ByteCount >> 9; BlockCount > 0; ) {
+
+ //
+ // Determine the size of this read based on the number of blocks
+ // required and where the current sector is on the current track.
+ //
+
+ EndSector = MINIMUM( SectorsPerTrack, (Sector + (BlockCount - 1)) );
+ TransferSize = (EndSector - Sector) + 1;
+ BlockCount -= TransferSize;
+ TransferSize <<= 9;
+
+ //
+ // Attempt to read the block(s) up to RETRY_COUNT times.
+ //
+
+ for (k = 0; k < RETRY_COUNT; k++) {
+
+ //
+ // Assume that the operation will be successful.
+ //
+
+ Success = TRUE;
+
+ //
+ // Do an explicit seek if this is a 360 K disk in a 1.2 MB drive.
+ //
+
+ if (CurrentDriveMediaConstants->CylinderShift != 0) {
+ if (!SendByte( COMMND_SEEK ) ||
+ !SendByte( (Head << 2) + DriveNumber ) || // head select & drive
+ !SendByte( Cylinder << CurrentDriveMediaConstants->CylinderShift )) {
+ return(EIO);
+ }
+
+// if (FwWaitForDeviceInterrupt(1 << (FLOPPY_VECTOR - DEVICE_VECTORS - 1),
+// FW_FLOPPY_TIMEOUT)) {
+ if (WaitForFloppyInterrupt(FW_FLOPPY_TIMEOUT)) {
+ return(EIO);
+ }
+
+ //
+ // Send the sense interrupt command.
+ //
+
+ if (!SendByte( COMMND_SENSE_INTERRUPT )) { // command
+ return(EIO);
+ }
+
+ //
+ // Read back the information from the drive and check the status of the
+ // recalibrate command.
+ //
+
+ DebugByte[0] = ReceiveByte();
+ DebugByte[1] = ReceiveByte();
+
+ if (DebugByte[1] != (Cylinder << CurrentDriveMediaConstants->CylinderShift)) {
+ return(EIO);
+ }
+
+ //
+ // Now try to read the ID from wherever we're at.
+ //
+
+ if (!SendByte( COMMND_READ_ID + COMMND_MFM ) || // command
+ !SendByte( DriveNumber | ((CurrentDriveMediaConstants->NumberOfHeads - 1) << 2) )) {
+ return(EIO);
+ }
+
+// if (FwWaitForDeviceInterrupt(1 << (FLOPPY_VECTOR - DEVICE_VECTORS - 1),
+// FW_FLOPPY_TIMEOUT)) {
+ if (WaitForFloppyInterrupt(FW_FLOPPY_TIMEOUT)) {
+ return(EIO);
+ }
+
+ for (i = 0; i < 7; i++) {
+ DebugByte[i] = ReceiveByte();
+ }
+
+ if ( ( DebugByte[0] !=
+ (UCHAR)(DriveNumber |
+ ((CurrentDriveMediaConstants->NumberOfHeads - 1) << 2))) ||
+ ( DebugByte[1] != 0 ) ||
+ ( DebugByte[2] != 0 ) ) {
+
+ return(EIO);
+ }
+
+ }
+
+ //
+ // Send the command and parameters for the operation.
+ //
+
+ if (ReadWrite == TRUE) {
+ if (!SendByte( COMMND_WRITE_DATA + COMMND_MFM )) {
+ return(EIO);
+ }
+ } else {
+ if (!SendByte( COMMND_READ_DATA + COMMND_MFM )) {
+ return(EIO);
+ }
+ }
+ if (!SendByte( (Head << 2) + DriveNumber ) || // head select & drive
+ !SendByte( Cylinder ) || // cylinder
+ !SendByte( Head ) || // head
+ !SendByte( Sector ) || // sector
+ !SendByte( 2 ) || // sector size; 2 => 512B/sec
+ !SendByte( EndSector ) || // end of track sector
+ !SendByte( CurrentDriveMediaConstants->ReadWriteGapLength ) ||
+ !SendByte( 0xff )) { // special sector size
+ return(EIO);
+ }
+
+ //
+ // Ensure that the floppy drive does not time-out.
+ //
+
+ for (j = 0; j < SECONDS_2; j += MICROSECONDS_10) {
+ if (READ_PORT_UCHAR((PUCHAR)&FLOPPY_CONTROL->MsrDsr.MainStatus)
+ > 127) {
+ break;
+ }
+
+ FwStallExecution(MICROSECONDS_10);
+ }
+
+ //
+ // Check for time-out; if one occurred, then return unsuccessful
+ // status.
+ //
+
+ if (j == SECONDS_2) {
+// FwPrint("Floppy timeout\r\n");
+ return EIO;
+ }
+
+ //
+ // Read the data from the appropriate block(s) and check the number
+ // of bytes actually read.
+ //
+
+ if (ReadWrite == TRUE) {
+ WriteFloppyFifo(Buffer,TransferSize);
+ } else {
+ TransferedBytes = ReadFloppyFifo(Buffer);
+ if (TransferedBytes != TransferSize) {
+ Success = FALSE;
+ }
+ }
+
+ //
+ // Read the status information from the device.
+ //
+
+ while (READ_PORT_UCHAR((PUCHAR)&FLOPPY_CONTROL->MsrDsr.MainStatus)
+ <= 127) {
+ }
+
+ for (i = 0; i < 7; i++) {
+ DebugByte[i] = ReceiveByte();
+ }
+
+ if (((DebugByte[0] >> 4) == 2) &&
+ (DebugByte[1] == 0) &&
+ (DebugByte[2] == 0) &&
+ Success) {
+ ;
+
+ } else {
+
+ if ((DebugByte[0] >> 4) != 4) {
+ Success = FALSE;
+ }
+
+ if (DebugByte[1] != 0x80) {
+ Success = FALSE;
+ }
+
+ if (DebugByte[2] != 0) {
+ Success = FALSE;
+ }
+ }
+
+ //
+ // If the operation was successful, exit the loop.
+ //
+
+ if (Success) {
+ Buffer += TransferSize;
+ break;
+ }
+
+ //
+ // The operation did not work. Attempt to recalibrate the
+ // device and wait for everything to settle out, and then
+ // try the operation again.
+ //
+
+ if (!Recalibrate(DriveNumber)) {
+// FwPrint("Floppy recalibration error\r\n");
+ return(EIO);
+ }
+ FwStallExecution(MILLISECONDS_15);
+ }
+
+ //
+ // If the operation was not successful after RETRY_COUNT tries, get
+ // out now.
+ //
+
+ if (!Success) {
+ Status = EIO;
+ break;
+ }
+
+ //
+ // If more data is needed, get the next place to read from. Note
+ // that if there is more data to be read, then the last sector
+ // just read was the last sector on this head.
+ //
+
+ if (BlockCount > 0) {
+ if (Head == 1) {
+ Cylinder += 1;
+ Head = 0;
+ } else {
+ Head = 1;
+ }
+ Sector = 1;
+ }
+
+ if (Success) {
+ Status = ESUCCESS;
+ }
+ }
+ return Status;
+}
+
+BOOLEAN
+Recalibrate(
+ UCHAR DriveNumber
+ )
+
+/*++
+
+Routine Description:
+
+ This routine issues a recalibrate command to the device, waits for it to
+ interrupt, sends it a sense interrupt command, and checks the result to
+ ensure that the recalibrate command worked properly.
+
+Arguments:
+
+ DriveNumber - Supplies the Floppy drive to recalibrate.
+
+Return Value:
+
+ Returns TRUE if the recalibrate was successful, FALSE if not.
+
+--*/
+
+{
+
+ //
+ // Send the recalibrate command to the device.
+ //
+
+ if (!SendByte( COMMND_RECALIBRATE ) || // command
+ !SendByte( DriveNumber )) { // drive select
+ return(FALSE);
+ }
+
+// if (FwWaitForDeviceInterrupt(1 << (FLOPPY_VECTOR - DEVICE_VECTORS - 1),
+// FW_FLOPPY_TIMEOUT)) {
+ if (WaitForFloppyInterrupt(FW_FLOPPY_TIMEOUT)) {
+// FwPrint("Floppy recalibrate timeout\r\n");
+ return(FALSE);
+ }
+
+ //
+ // Send the sense interrupt command.
+ //
+
+ if (!SendByte( COMMND_SENSE_INTERRUPT )) { // command
+ return(FALSE);
+ }
+
+ //
+ // Read back the information from the drive and check the status of the
+ // recalibrate command.
+ //
+
+ DebugByte[0] = ReceiveByte();
+ if ((DebugByte[0] >> 4) != 2) {
+ return FALSE;
+ }
+
+ DebugByte[1] = ReceiveByte();
+
+ if ((READ_PORT_UCHAR((PUCHAR)&FLOPPY_CONTROL->MsrDsr.MainStatus) &
+ STATUS_IO_READY_MASK) == STATUS_READ_READY) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+UCHAR
+ReceiveByte(
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads the next byte from the floppy FIFO register.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The function value is the value of the byte read from the floppy FIFO.
+
+--*/
+
+{
+
+ ULONG i;
+
+ //
+ // Check status register for readiness to receive data.
+ //
+
+ for (i = 0; i < MICROSECONDS_250; i += MICROSECONDS_10) {
+ if ((READ_PORT_UCHAR((PUCHAR)&FLOPPY_CONTROL->MsrDsr.MainStatus) &
+ STATUS_IO_READY_MASK) == STATUS_READ_READY) {
+ return READ_PORT_UCHAR((PUCHAR)&FLOPPY_CONTROL->Fifo);
+ }
+
+ FwStallExecution(MICROSECONDS_10);
+ }
+
+ //
+ // A timeout occurred while attempting to read data from the floppy fifo.
+ // Output an error message and return.
+ //
+
+// FwPrint("Error reading from floppy fifo\r\n");
+ return(0xFF);
+}
+
+BOOLEAN
+SendByte(
+ IN UCHAR SourceByte
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sends a specified byte to the floppy FIFO register.
+
+Arguments:
+
+ SourceByte - Byte to be sent to the controller.
+
+Return Value:
+
+ If the byte was successfully written to the floppy FIFO, TRUE is returned,
+ otherwise FALSE is returned.
+
+--*/
+
+{
+
+ ULONG i;
+
+ //
+ // Check status register for readiness to receive data.
+ //
+
+ for (i = 0; i < MICROSECONDS_250; i += MICROSECONDS_10) {
+ if ((READ_PORT_UCHAR((PUCHAR)&FLOPPY_CONTROL->MsrDsr.MainStatus) &
+ STATUS_IO_READY_MASK) == STATUS_WRITE_READY) {
+ WRITE_PORT_UCHAR((PUCHAR)&FLOPPY_CONTROL->Fifo, SourceByte);
+ return(TRUE);
+ }
+
+ FwStallExecution(MICROSECONDS_10);
+ }
+
+ //
+ // A timeout occurred while attempting to write data to the floppy fifo.
+ // Output an error message and return.
+ //
+
+// FwPrint("Error writing to floppy fifo\r\n");
+ return(FALSE);
+}
+
+VOID
+ClearFloppyFifo(
+ IN VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine empties the fifo.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG i;
+
+ //
+ // Check status register for readiness to receive data.
+ //
+ while ((READ_PORT_UCHAR((PUCHAR)&FLOPPY_CONTROL->MsrDsr.MainStatus) &
+ STATUS_IO_READY_MASK) == STATUS_READ_READY) {
+ READ_PORT_UCHAR((PUCHAR)&FLOPPY_CONTROL->Fifo);
+ FwStallExecution(MICROSECONDS_10);
+ }
+}
+
+
+ARC_STATUS
+FloppyDatarateSpecifyConfigure(
+ IN DRIVE_MEDIA_TYPE DriveMediaType,
+ IN UCHAR DriveNumber
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called to set up the controller every time a new type
+ of diskette is to be accessed. It issues the CONFIGURE command,
+ does a SPECIFY, sets the data rate, and RECALIBRATEs the drive.
+
+Arguments:
+
+ DriveMediaType - supplies the drive type/media density combination.
+
+ DriveNumber - supplies the drive number.
+
+Return Value:
+
+ ESUCCESS if the controller is properly prepared; appropriate
+ error propogated otherwise.
+
+--*/
+
+{
+ UCHAR Configure;
+
+ //
+ // Don't enable implied seeks when there is a 360K disk in a 1.2M drive.
+ //
+
+ if (DriveMediaConstants[DriveMediaType].CylinderShift) {
+ Configure = 0x18;
+ } else {
+ Configure = 0x58;
+ }
+
+ //
+ // Issue the configuration command.
+ //
+
+ if (!SendByte( COMMND_CONFIGURE ) || // command
+ !SendByte( 0x00 ) || // required 0
+ !SendByte( Configure ) || // implied seeks, disable polling & threshold = 8
+ !SendByte( 0x00 ) || // precompensation track = 0
+
+ //
+ // Issue SPECIFY command to program the head load and unload
+ // rates, the drive step rate, and the DMA data transfer mode.
+ //
+
+ !SendByte( COMMND_SPECIFY ) || // command
+ !SendByte( DriveMediaConstants[DriveMediaType].StepRateHeadUnloadTime) ||
+ !SendByte( DriveMediaConstants[DriveMediaType].HeadLoadTime + 1)) {
+ return(EIO);
+ }
+
+ //
+ // Program the data rate
+ //
+
+ WRITE_PORT_UCHAR((PUCHAR)&FLOPPY_CONTROL->MsrDsr.DataRateSelect,
+ DriveMediaConstants[DriveMediaType].DataTransferRate );
+
+ //
+ // Recalibrate the drive, now that we've changed all its
+ // parameters.
+ //
+
+ if (Recalibrate(DriveNumber)) {
+ return(ESUCCESS);
+ } else {
+// FwPrint("Floppy recalibration error\r\n");
+ return(EIO);
+ }
+}
+
+ARC_STATUS
+FloppyDetermineMediaType(
+ IN OUT PFLOPPY_CONTEXT FloppyContext,
+ OUT PMEDIA_TYPE mediaType
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called by FloppyBootIO() when the media type is
+ unknown. It assumes the largest media supported by the drive is
+ available, and keeps trying lower values until it finds one that
+ works.
+
+Arguments:
+
+ FloppyContext - supplies a pointer to the floppy context structure.
+
+ mediaType - supplies a pointer to a variable that receives the
+ type of the media in the drive.
+
+Return Value:
+
+ ESUCCESS if the type of the media is determined; appropriate
+ error propogated otherwise.
+
+--*/
+
+{
+ ARC_STATUS Status;
+ BOOLEAN mediaTypesExhausted = FALSE;
+ DRIVE_MEDIA_TYPE DriveMediaType;
+ UCHAR DriveNumber;
+ ULONG i;
+
+ //
+ // Assume that the largest supported media is in the drive. If that
+ // turns out to be untrue, we'll try successively smaller media types
+ // until we find what's really in there (or we run out and decide
+ // that the media isn't formatted).
+ //
+
+ DriveMediaType =
+ DriveMediaLimits[FloppyContext->DriveType].HighestDriveMediaType;
+
+ DriveNumber = FloppyContext->DiskId;
+
+ do {
+
+ Status = FloppyDatarateSpecifyConfigure( DriveMediaType, DriveNumber );
+
+ if ( Status != ESUCCESS ) {
+
+ //
+ // The SPECIFY or CONFIGURE commands resulted in an error.
+ // Force ourselves out of this loop and return error.
+ //
+
+ mediaTypesExhausted = TRUE;
+
+ } else {
+
+ CurrentDriveMediaConstants = &DriveMediaConstants[DriveMediaType];
+
+ //
+ // Now try to read the ID from wherever we're at.
+ //
+
+ if (!SendByte( COMMND_READ_ID + COMMND_MFM ) || // command
+ !SendByte( DriveNumber | ((CurrentDriveMediaConstants->NumberOfHeads - 1) << 2) )) {
+ return(EIO);
+ }
+
+// if (FwWaitForDeviceInterrupt(1 << (FLOPPY_VECTOR - DEVICE_VECTORS - 1),
+// FW_FLOPPY_TIMEOUT)) {
+ if (WaitForFloppyInterrupt(FW_FLOPPY_TIMEOUT)) {
+// FwPrint("Floppy determine media timeout\r\n");
+ return(EIO);
+ }
+
+ for (i = 0; i < 7; i++) {
+ DebugByte[i] = ReceiveByte();
+ }
+
+ if ( ( DebugByte[0] !=
+ (UCHAR)(DriveNumber |
+ ((CurrentDriveMediaConstants->NumberOfHeads - 1) << 2))) ||
+ ( DebugByte[1] != 0 ) ||
+ ( DebugByte[2] != 0 ) ) {
+
+ DriveMediaType--;
+
+ Status = ENXIO;
+
+ //
+ // Next comparison must be signed, for when
+ // LowestDriveMediaType = 0.
+ //
+
+ if ( (CHAR)( DriveMediaType ) <
+ (CHAR)( DriveMediaLimits[FloppyContext->DriveType].LowestDriveMediaType )) {
+
+ mediaTypesExhausted = TRUE;
+
+ }
+ }
+ }
+
+ } while ( ( ( Status != ESUCCESS ) ) && !( mediaTypesExhausted ) );
+
+ if ( Status == ESUCCESS ) {
+
+ FloppyContext->SectorsPerTrack =
+ CurrentDriveMediaConstants->SectorsPerTrack;
+
+ *mediaType = CurrentDriveMediaConstants->MediaType;
+ }
+ return Status;
+}
+
+ULONG
+ReadFloppyFifo (
+ IN OUT PUCHAR Buffer
+ )
+
+/*++
+
+Routine Description:
+
+ This reads data from the floppy fifo.
+
+Arguments:
+
+ Buffer - Pointer to the buffer that receives the data read.
+
+Return Value:
+
+ The number of bytes read.
+
+--*/
+{
+ ULONG BytesRead = 0;
+ UCHAR MSR;
+
+ while (TRUE) {
+
+ // Loop until DIO and RQM are both set.
+ while (
+ ((MSR = READ_PORT_UCHAR((PUCHAR)&FLOPPY_CONTROL->MsrDsr.MainStatus))
+ & (FLOPPY_MSR_DIO | FLOPPY_MSR_RQM))
+ != (FLOPPY_MSR_DIO | FLOPPY_MSR_RQM)
+ ) {
+ }
+
+ // If the non-DMA bit is clear, end of transfer.
+ if ((MSR & FLOPPY_MSR_NONDMA) == 0) {
+ return (BytesRead);
+ }
+
+ // Read the byte, increment pointer and total, until done.
+ *Buffer++ = READ_PORT_UCHAR((PUCHAR)&FLOPPY_CONTROL->Fifo);
+ BytesRead++;
+ }
+}
+
+VOID
+WriteFloppyFifo(
+ IN PUCHAR Buffer,
+ IN ULONG Size
+ )
+
+/*++
+
+Routine Description:
+
+ This writes data to the floppy fifo.
+
+Arguments:
+
+ Buffer - Pointer to the buffer that contains the data to be written.
+
+ Size - The number of bytes to be written.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ while (Size) {
+
+ // Loop until DIO is clear and RQM is set.
+ while (
+ (READ_PORT_UCHAR((PUCHAR)&FLOPPY_CONTROL->MsrDsr.MainStatus)
+ & (FLOPPY_MSR_DIO | FLOPPY_MSR_RQM))
+ != FLOPPY_MSR_RQM
+ ) {
+ }
+
+ //
+ // Write the byte, increment pointer, decrement count, until done.
+ // Remember, C does call by value.
+ //
+
+ WRITE_PORT_UCHAR((PUCHAR)&FLOPPY_CONTROL->Fifo, *Buffer++);
+ --Size;
+ }
+
+ //
+ // All bytes written to fifo. Wait until the floppy controller
+ // empties it.
+ //
+
+ while (
+ (READ_PORT_UCHAR((PUCHAR)&FLOPPY_CONTROL->MsrDsr.MainStatus)
+ & FLOPPY_MSR_NONDMA)
+ != 0 ) {
+ }
+
+
+ return;
+
+}
+
+ARC_STATUS
+WaitForFloppyInterrupt(
+ ULONG Timeout
+ )
+
+/*++
+
+Routine Description:
+
+ This waits until the floppy controller has an interrupt pending,
+ or the requested Timeout period has been reached.
+
+ The Jazz code enables interrupts for the keyboard and individual
+ devices. In actuality, the only non-keyboard device it enables interrupts
+ for is the floppy controller. For Alpha we avoid dealing
+ with interrupts in the firmware code to keep the PALcode simple. So
+ every Jazz call to "FwWaitForDeviceInterrupt" has been changed to
+ this function.
+
+Arguments:
+
+ Timeout - A timeout value in seconds. Note that a timeout of 0 gives
+ an actual timeout of between 0 and 1, a timeout of 1 gives
+ an actual timeout of between 1 and 2, and so on.
+
+Return Value:
+
+ ESUCCESS if an interrupt is floppy interrupt is detected.
+ EIO if a timeout occurs.
+
+--*/
+
+{
+ ULONG Time1;
+
+
+ Time1 = FwGetRelativeTime();
+
+ // Ask for the interrupt wires
+ WRITE_PORT_UCHAR((PUCHAR)EISA_INT_OCW3, EISA_INT_OCW3_IRR);
+
+ //
+ // 0x40 is irq6, which is the floppy controller. I should make this
+ // into a #define.
+ //
+ while (
+ (READ_PORT_UCHAR((PUCHAR)EISA_INT_OCW3) & 0x40)
+ == 0) {
+ if ((FwGetRelativeTime() - Time1) > (Timeout + 1)) {
+ return(EIO);
+ }
+ }
+
+ return(ESUCCESS);
+}
diff --git a/private/ntos/fw/alpha/jxfwhal.h b/private/ntos/fw/alpha/jxfwhal.h
new file mode 100644
index 000000000..6af81d171
--- /dev/null
+++ b/private/ntos/fw/alpha/jxfwhal.h
@@ -0,0 +1,109 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ jxfwhal.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ Jazz specific interfaces, defines and structures.
+
+ This is a modified version of \nt\private\ntos\hal\alpha\jxhalp.h.
+
+Author:
+
+ Jeff Havens (jhavens) 09-Aug-91
+
+
+Revision History:
+
+ 21-July-1992 John DeRosa [DEC]
+
+ Modified for the Alpha/Jensen port.
+
+--*/
+
+#ifndef _JXFWHAL_
+#define _JXFWHAL_
+
+//
+// Define global data used to locate the EISA control space and the realtime
+// clock registers.
+//
+
+extern PVOID HalpEisaControlBase;
+
+// Not present in Jensen.
+//extern PVOID HalpRealTimeClockBase;
+
+
+//
+// Define adapter object structure. This is abbreviated and is not
+// the full structure found in hal\alpha\jxhalp.h.
+//
+
+typedef struct _ADAPTER_OBJECT {
+ CSHORT Type;
+ CSHORT Size;
+ struct _ADAPTER_OBJECT *MasterAdapter;
+ ULONG MapRegistersPerChannel;
+ PVOID AdapterBaseVa;
+ PVOID MapRegisterBase;
+ ULONG NumberOfMapRegisters;
+ ULONG CommittedMapRegisters;
+ BOOLEAN AdapterInUse;
+ UCHAR ChannelNumber;
+ UCHAR AdapterNumber;
+ UCHAR AdapterMode;
+ BOOLEAN NeedsMapRegisters;
+ BOOLEAN MasterDevice;
+ BOOLEAN Width16Bits;
+ PUCHAR PagePort;
+} ADAPTER_OBJECT;
+
+//
+// Define function prototypes.
+//
+
+PADAPTER_OBJECT
+HalpAllocateEisaAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescription
+ );
+
+BOOLEAN
+HalpCreateEisaStructures(
+ VOID
+ );
+
+VOID
+HalpDisableEisaInterrupt(
+ IN CCHAR Vector
+ );
+
+BOOLEAN
+HalpEisaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+VOID
+HalpEisaMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ );
+
+VOID
+HalpEnableEisaInterrupt(
+ IN CCHAR Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+#define HalpAllocateEisaAdapter(DeviceDescription) NULL
+
+#endif // _JXFWHAL_
diff --git a/private/ntos/fw/alpha/jxhwsup.c b/private/ntos/fw/alpha/jxhwsup.c
new file mode 100644
index 000000000..a43a31400
--- /dev/null
+++ b/private/ntos/fw/alpha/jxhwsup.c
@@ -0,0 +1,1936 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ jxhwsup.c
+
+Abstract:
+
+ This module contains the IopXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would normally reside in the internal.c module.
+
+ Like the MIPS module, this is a hacked-up version of
+ \nt\private\ntos\hal\alpha\jxhwsup.c.
+
+
+Author:
+
+ Jeff Havens (jhavens) 14-Feb-1990
+ Miche Baker-Harvey (miche) 22-May-1992
+ Jeff McLeman (mcleman) 27-May-1992
+
+Environment:
+
+ Kernel mode, local to I/O system
+
+Revision History:
+
+ 3-August-1992 John DeRosa
+
+ Made this from \nt\private\ntos\hal\alpha\jxhwsup.c and
+ \nt\private\ntos\fw\mips\jxhwsup.c.
+
+--*/
+
+#include "fwp.h"
+#include "ntalpha.h"
+#include "jxfwhal.h"
+
+#ifdef JENSEN
+#include "jnsndma.h"
+#else
+#include "mrgndma.h" // morgan
+#endif
+
+#include "eisa.h"
+#include "jxisa.h"
+
+
+//
+// Firmware-specific definitions to aid compilation and linking.
+//
+
+//
+// HalpBusType is used by the Hal so to run properly on EISA or ISA
+// machines. It is a static that is initialized in hal\alpha\xxinithl.c.
+
+#ifdef EISA_PLATFORM
+
+//
+// This definition is correct for any EISA-based Alpha machines.
+//
+
+#define HalpBusType MACHINE_TYPE_EISA
+
+#else
+
+#define HalpBusType MACHINE_TYPE_ISA
+
+#endif
+
+//
+// This is a BOOLEAN variable in the real Hal code.
+//
+
+#define LessThan16Mb (MemorySize <= (16 * 1024 * 1024))
+
+#define HAL_32MB 0x2000000
+
+PVOID HalpEisaControlBase;
+
+//
+// The following is an array of adapter object structures for the Eisa DMA
+// channels.
+//
+
+//
+// Define the area for the Eisa objects
+//
+
+PADAPTER_OBJECT HalpEisaAdapter[8];
+
+PADAPTER_OBJECT MasterAdapterObject;
+
+//
+// function prototypes
+//
+
+BOOLEAN
+HalpGrowMapBuffers(
+ PADAPTER_OBJECT AdapterObject,
+ ULONG Amount
+ );
+
+
+PADAPTER_OBJECT
+IopAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID ChannelNumber
+ );
+
+VOID
+HalpCopyBufferMap(
+ IN PMDL Mdl,
+ IN PTRANSLATION_ENTRY translationEntry,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ );
+
+QUASI_VIRTUAL_ADDRESS
+HalCreateQva(
+ IN PHYSICAL_ADDRESS PA,
+ IN PVOID VA
+ );
+
+VOID
+HalpCopyBufferMap(
+ IN PMDL Mdl,
+ IN PTRANSLATION_ENTRY translationEntry,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine copies the specified data between the user buffer and the
+ map register buffer. First, the user buffer is mapped, if need be then
+ the data is copied. Finally, the user buffer will be unmapped, if need be.
+
+Arguments:
+
+ Mdl - Pointer to the Mdl that describes the pages of memory that are
+ being read or written.
+
+ translationEntry - The address of the base map register that has been
+ allocated to the device driver for use in mapping the xfer.
+
+ CurrentVa - Current Virtual Address in the buffer described by the Mdl
+ that the transfer is being done to or from.
+
+ Length - The length of the transfer. This determines the number of map
+ registers that need to be written to map the transfer.
+
+ WriteToDevice - A Boolean value that indicates whether this is a write
+ to the device from memory of vise-versa.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+
+ PCCHAR bufferAddress;
+ PCCHAR mapAddress;
+
+
+ //
+ // Get the system address of the MDL.
+ //
+
+ //bufferAddress = MmGetSystemAddressForMdl(Mdl);
+
+ //
+ // Calculate the actual start of the buffer based on the system VA and
+ // the current VA.
+ //
+
+ //bufferAddress += (PCCHAR) CurrentVa - (PCCHAR) MmGetMdlVirtualAddress(Mdl);
+ bufferAddress = (PCCHAR) CurrentVa;
+
+ mapAddress = (PCCHAR) translationEntry->VirtualAddress +
+ BYTE_OFFSET(CurrentVa);
+
+ //
+ // Copy the data between the user buffer and the map buffer.
+ //
+
+ if (WriteToDevice) {
+
+ RtlMoveMemory( mapAddress, bufferAddress, Length);
+
+ } else {
+
+ RtlMoveMemory ( bufferAddress, mapAddress, Length);
+
+ }
+}
+
+NTSTATUS
+IoAllocateAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PDEVICE_OBJECT DeviceObject,
+ IN ULONG NumberOfMapRegisters,
+ IN PDRIVER_CONTROL ExecutionRoutine,
+ IN PVOID Context
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates the adapter channel specified by the adapter object.
+ This is accomplished by placing the device object of the driver that wants
+ to allocate the adapter on the adapter's queue. If the queue is already
+ "busy", then the adapter has already been allocated, so the device object
+ is simply placed onto the queue and waits until the adapter becomes free.
+
+ Once the adapter becomes free (or if it already is), then the driver's
+ execution routine is invoked.
+
+ Also, a number of map registers may be allocated to the driver by specifying
+ a non-zero value for NumberOfMapRegisters. Then the map register must be
+ allocated from the master adapter. Once there are a sufficient number of
+ map registers available, then the execution routine is called and the
+ base address of the allocated map registers in the adapter is also passed
+ to the driver's execution routine.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+
+ DeviceObject - Pointer to the driver's device object that represents the
+ device allocating the adapter.
+
+ NumberOfMapRegisters - The number of map registers that are to be allocated
+ from the channel, if any.
+
+ ExecutionRoutine - The address of the driver's execution routine that is
+ invoked once the adapter channel (and possibly map registers) have been
+ allocated.
+
+ Context - An untyped longword context parameter passed to the driver's
+ execution routine.
+
+
+Return Value:
+
+ Returns STATUS_SUCESS unless too many map registers are requested.
+
+Notes:
+
+ Note that this routine MUST be invoked at DISPATCH_LEVEL or above.
+
+--*/
+
+{
+ PADAPTER_OBJECT MasterAdapter;
+ IO_ALLOCATION_ACTION Action;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ if (AdapterObject->MasterAdapter != NULL) {
+ MasterAdapter = AdapterObject->MasterAdapter;
+ } else {
+ MasterAdapter = AdapterObject;
+ }
+
+ //
+ // Make sure the adapter is free.
+ //
+
+ if (AdapterObject->AdapterInUse) {
+ DbgPrint("IoAllocateAdapterChannel: Called while adapter in use.\n");
+ }
+
+ //
+ // Make sure there are enough map registers.
+ //
+
+ AdapterObject->NumberOfMapRegisters = NumberOfMapRegisters;
+
+ if ((NumberOfMapRegisters != 0) && AdapterObject->NeedsMapRegisters) {
+
+ if (NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ DbgPrint("IoAllocateAdapterChannel: Out of map registers.\r\n");
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ AdapterObject->MapRegisterBase =
+ (PVOID)(PTRANSLATION_ENTRY)MasterAdapter->MapRegisterBase;
+
+ } else {
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ Action = ExecutionRoutine( DeviceObject,
+ DeviceObject->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Context );
+
+ //
+ // If the driver wishes to keep the map registers then
+ // increment the current base and decrease the number of existing map
+ // registers.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+
+ AdapterObject->MapRegistersPerChannel -= NumberOfMapRegisters;
+ (PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase +=
+ NumberOfMapRegisters;
+
+ } else if (Action == KeepObject) {
+
+ AdapterObject->AdapterInUse = TRUE;
+
+ } else if (Action == DeallocateObject) {
+
+ IoFreeAdapterChannel( AdapterObject );
+
+ }
+
+ return(STATUS_SUCCESS);
+}
+
+PADAPTER_OBJECT
+HalGetAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescriptor,
+ IN OUT PULONG NumberOfMapRegisters
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the appropriate adapter object for the device defined
+ in the device description structure. Two bus types are supported for the
+ Jensen system: Isa, and Eisa.
+
+Arguments:
+
+ DeviceDescriptor - Supplies a description of the deivce.
+
+ NumberOfMapRegisters - Returns the maximum number of map registers which
+ may be allocated by the device driver.
+
+Return Value:
+
+ A pointer to the requested adapter object or NULL if an adapter could not
+ be created.
+
+--*/
+
+{
+ PADAPTER_OBJECT adapterObject;
+ PVOID adapterBaseVa;
+ ULONG channelNumber;
+ ULONG controllerNumber;
+ DMA_EXTENDED_MODE extendedMode;
+ UCHAR adapterMode;
+ ULONG numberOfMapRegisters;
+ BOOLEAN useChannel;
+ BOOLEAN eisaSystem;
+ ULONG maximumLength;
+
+ eisaSystem = HalpBusType == MACHINE_TYPE_EISA ? TRUE : FALSE;
+
+ //
+ // Determine if the channel number is important. Master cards on
+ // Eisa systems do not use channel numbers.
+ //
+
+ if (DeviceDescriptor->InterfaceType != Isa &&
+ DeviceDescriptor->Master) {
+
+ useChannel = FALSE;
+ } else {
+
+ useChannel = TRUE;
+ }
+
+ //
+ // Limit the max length to 2GB. This is done to make BYTES_TO_PAGES
+ // work correctly.
+ //
+
+ maximumLength = DeviceDescriptor->MaximumLength & 0x7FFFFFFF;
+
+ //
+ // Channel 4 cannot be used since it reserved for chaining. Return
+ // NULL if it has been requested.
+ //
+
+ if (DeviceDescriptor->DmaChannel == 4 && useChannel) {
+ return(NULL);
+ }
+
+ //
+ // Determine the number of map registers for this device
+ //
+
+ if (DeviceDescriptor->ScatterGather && (LessThan16Mb ||
+ DeviceDescriptor->InterfaceType == Eisa)) {
+
+ //
+ // Since the device is a master and does scatter/gather
+ // we don't need any map registers.
+ //
+
+ numberOfMapRegisters = 0;
+
+ } else {
+
+
+ //
+ // Return number of map registers requested based on the maximum
+ // transfer length.
+ //
+
+ //numberOfMapRegisters = BYTES_TO_PAGES(
+ // maximumLength
+ // ) + 1;
+ numberOfMapRegisters = DMA_TRANSLATION_LIMIT / sizeof(TRANSLATION_ENTRY);
+
+ numberOfMapRegisters = numberOfMapRegisters > MAXIMUM_ISA_MAP_REGISTER ? MAXIMUM_ISA_MAP_REGISTER : numberOfMapRegisters;
+
+ //
+ // If this device is not a master then it only needs one register
+ // and does scatter/gather.
+ //
+
+ if (DeviceDescriptor->ScatterGather && !DeviceDescriptor->Master) {
+
+ numberOfMapRegisters = 1;
+
+ }
+ }
+
+ //
+ // Set the channel number.
+ //
+
+ channelNumber = DeviceDescriptor->DmaChannel & 0x03;
+
+ //
+ // set the adapter base address to the Base address register and
+ // controller number.
+
+ if (!(DeviceDescriptor->DmaChannel & 0x04)) {
+
+ controllerNumber = 1;
+ adapterBaseVa = &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort;
+ } else {
+
+ controllerNumber = 2;
+ adapterBaseVa = &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort;
+
+ }
+
+ //
+ // Determine if a new adapter object is necessary
+ //
+
+ if (useChannel && HalpEisaAdapter[DeviceDescriptor->DmaChannel] != NULL) {
+
+ adapterObject = HalpEisaAdapter[DeviceDescriptor->DmaChannel];
+
+ } else {
+
+ //
+ // Allocate an adapter object
+ //
+
+ adapterObject = (PADAPTER_OBJECT) IopAllocateAdapter(
+ numberOfMapRegisters,
+ adapterBaseVa,
+ NULL);
+
+ if (adapterObject == NULL) {
+
+ return(NULL);
+
+ }
+
+ if (useChannel) {
+
+ HalpEisaAdapter[DeviceDescriptor->DmaChannel] = adapterObject;
+
+ }
+
+ //
+ // Set the maximum number of map registers for this channel based
+ // on the number requested andthe type of the device.
+ //
+
+ if (numberOfMapRegisters) {
+
+ //
+ // The specified number of registers are actually allowed to be
+ // allocated.
+ //
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+
+ //
+ // Increase the commitment for the map registers
+ //
+
+ if (DeviceDescriptor->Master) {
+
+ //
+ // Double the commitment for Master I/O devices
+ //
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters * 2;
+
+ } else {
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters;
+
+ }
+
+ //
+ // If the committed map registers is significantly greater than
+ // the number allocated, then grow the map buffer.
+ //
+
+ if (MasterAdapterObject->CommittedMapRegisters >
+ MasterAdapterObject->NumberOfMapRegisters &&
+ MasterAdapterObject->CommittedMapRegisters -
+ MasterAdapterObject->NumberOfMapRegisters >
+ MAXIMUM_ISA_MAP_REGISTER ) {
+
+ HalpGrowMapBuffers(
+ MasterAdapterObject,
+ INCREMENT_MAP_BUFFER_SIZE);
+
+ }
+
+ adapterObject->NeedsMapRegisters = TRUE;
+
+ } else {
+
+ //
+ // No real registers were allocated. If this is a master, then
+ // it is allowed as many registers as it wants.
+ //
+
+ adapterObject->NeedsMapRegisters = FALSE;
+
+ if (DeviceDescriptor->Master) {
+
+ adapterObject->MapRegistersPerChannel = BYTES_TO_PAGES(
+ maximumLength) + 1;
+ } else {
+
+ //
+ // The device only gets one register. It must call
+ // IoMapTransfer repeatedly to do a large transfer.
+ //
+
+ adapterObject->MapRegistersPerChannel = 1;
+ }
+ }
+ }
+
+ *NumberOfMapRegisters = adapterObject->MapRegistersPerChannel;
+
+ //
+ // If the channel number is not used, we are done. If we do use one,
+ // we have to set up the following.
+ //
+
+ if (!useChannel) {
+
+ return(adapterObject);
+
+ }
+
+ //
+ // Setup pointers to the various and sundry registers.
+ //
+
+ adapterObject->ChannelNumber = (UCHAR) channelNumber;
+
+ if (controllerNumber == 1) {
+
+ switch (channelNumber) {
+
+ case 0:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel0;
+ break;
+ case 1:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel1;
+ break;
+ case 2:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel2;
+ break;
+ case 3:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel3;
+ break;
+
+ }
+
+ //
+ // Set the adapter number
+ //
+
+ adapterObject->AdapterNumber = 1;
+
+ //
+ // Save the extended mode register
+ //
+
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1ExtendedModePort;
+
+ } else {
+
+ switch (channelNumber) {
+
+ case 1:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel5;
+ break;
+ case 2:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel6;
+ break;
+ case 3:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel7;
+ break;
+ }
+
+ //
+ // Set the adapter number
+ //
+
+ adapterObject->AdapterNumber = 2;
+
+ //
+ // Save the extended mode register
+ //
+
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2ExtendedModePort;
+
+ }
+
+ adapterObject->Width16Bits = FALSE;
+
+ if (eisaSystem) {
+
+ //
+ // Init the extended mode port
+ //
+
+ *((PUCHAR) &extendedMode) = 0;
+
+ switch (DeviceDescriptor->DmaSpeed) {
+ case Compatible:
+ extendedMode.TimingMode =COMPATIBILITY_TIMING;
+ break;
+
+ case TypeA:
+ extendedMode.TimingMode = TYPE_A_TIMING;
+ break;
+
+ case TypeB:
+ extendedMode.TimingMode = TYPE_B_TIMING;
+ break;
+
+ case TypeC:
+ extendedMode.TimingMode = BURST_TIMING;
+ break;
+
+ default:
+ /* error return, don't bother to dereference the object. */
+ //ObDereferenceObject(adapterObject);
+ return(NULL);
+
+ }
+
+ switch (DeviceDescriptor->DmaWidth) {
+ case Width8Bits:
+ extendedMode.TransferSize = BY_BYTE_8_BITS;
+ break;
+
+ case Width16Bits:
+ extendedMode.TransferSize = BY_BYTE_16_BITS;
+ break;
+
+ case Width32Bits:
+ extendedMode.TransferSize = BY_BYTE_32_BITS;
+ break;
+
+ default:
+ /* error return, don't bother to dereference the object. */
+ //ObDereferenceObject(adapterObject);
+ return(NULL);
+
+ }
+
+ WRITE_PORT_UCHAR( adapterBaseVa, *((PUCHAR) &extendedMode));
+ } else if (!DeviceDescriptor->Master) {
+
+ switch (DeviceDescriptor->DmaWidth) {
+ case Width8Bits:
+
+ //
+ // The channel must use controller 1.
+ //
+ if (controllerNumber != 1) {
+ /* error return, don't bother to dereference the object. */
+ //ObDereferenceObject(adapterObject);
+ return(NULL);
+ }
+ break;
+
+ case Width16Bits:
+
+ //
+ // The channel must use controller 2
+ //
+
+ if (controllerNumber != 2) {
+ /* error return, don't bother to dereference the object. */
+ //ObDereferenceObject(adapterObject);
+ return(NULL);
+ }
+ adapterObject->Width16Bits = TRUE;
+ break;
+
+ default:
+ /* error return, don't bother to dereference the object. */
+ //ObDereferenceObject(adapterObject);
+ return(NULL);
+
+ }
+ }
+
+ //
+ // Init the adapter mode register to the correct parameters and save
+ // them in the adapter object.
+ //
+
+ adapterMode = 0;
+ ((PDMA_EISA_MODE) &adapterMode)->Channel = adapterObject->ChannelNumber;
+
+ if (DeviceDescriptor->Master) {
+
+ adapterObject->MasterDevice = TRUE;
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+
+ //
+ // Set the mode and grant the request.
+ //
+
+ if (adapterObject->AdapterNumber == 1) {
+
+ //
+ // This is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+ dmaControl = adapterObject->AdapterBaseVa;
+ WRITE_PORT_UCHAR(&dmaControl->Mode, adapterMode);
+
+ //
+ // unmask the DMA channel
+ //
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This is form DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+ dmaControl = adapterObject->AdapterBaseVa;
+ WRITE_PORT_UCHAR(&dmaControl->Mode, adapterMode);
+
+ //
+ // unmask the DMA channel
+ //
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ }
+
+ } else if (DeviceDescriptor->DemandMode) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = DEMAND_REQUEST_MODE;
+ } else {
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = SINGLE_REQUEST_MODE;
+ }
+
+ if (DeviceDescriptor->AutoInitialize) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->AutoInitialize = 1;
+ }
+
+ adapterObject->AdapterMode = adapterMode;
+
+
+ return(adapterObject);
+ }
+
+BOOLEAN
+HalpGrowMapBuffers(
+ PADAPTER_OBJECT AdapterObject,
+ ULONG Amount
+ )
+/*++
+
+Routine Description:
+
+ This function attempts to allocate additional map buffers for use by I/O
+ devices. The map register table is updated to indicate the additional
+ buffers.
+
+Arguments:
+
+ AdapterObject - Supplies the adapter object for which the buffers are to be
+ allocated.
+
+ Amount - Indicates the size of the map buffers which should be allocated.
+
+Return Value:
+
+ TRUE is returned if the memory could be allocated.
+
+ FALSE is returned if the memory could not be allocated.
+
+--*/
+{
+ ULONG MapBufferPhysicalAddress;
+ PVOID MapBufferVirtualAddress;
+ PTRANSLATION_ENTRY TranslationEntry;
+ LONG NumberOfPages;
+ LONG i;
+ BOOLEAN eisaSystem;
+ PHYSICAL_ADDRESS physicalAddress;
+
+ eisaSystem = HalpBusType == MACHINE_TYPE_EISA ? TRUE : FALSE;
+
+ NumberOfPages = BYTES_TO_PAGES(Amount);
+
+ //
+ // Make sure there is room for the addition pages. The maximum number of
+ // slots needed is equal to NumberOfPages + Amount / 64K + 1.
+ //
+
+ i = BYTES_TO_PAGES(MAXIMUM_MAP_BUFFER_SIZE) - (NumberOfPages +
+ (NumberOfPages * PAGE_SIZE) / 0x10000 + 1 +
+ AdapterObject->NumberOfMapRegisters);
+
+ if (i < 0) {
+
+ //
+ // Reduce the allocatation amount to so it will fit.
+ //
+
+ NumberOfPages += i;
+ }
+
+ if (NumberOfPages <= 0) {
+ //
+ // No more memory can be allocated.
+ //
+
+ return(FALSE);
+
+ }
+
+ //
+ // Allocate the map buffers.
+ //
+ // Remember: for the firmware, virtual = physical.
+ //
+
+ MapBufferVirtualAddress = FwAllocatePool(NumberOfPages * PAGE_SIZE);
+
+ if (MapBufferVirtualAddress == NULL) {
+ return(FALSE);
+ }
+
+ //
+ // Get the physical address of the map base.
+ //
+
+ MapBufferPhysicalAddress = (ULONG)MapBufferVirtualAddress;
+
+ //
+ // Initialize the map registers where memory has been allocated.
+ //
+
+ TranslationEntry = ((PTRANSLATION_ENTRY) AdapterObject->MapRegisterBase) +
+ AdapterObject->NumberOfMapRegisters;
+
+ for (i = 0; (ULONG) i < NumberOfPages; i++) {
+
+ //
+ // Make sure the previous entry is physically contiguous with the next
+ // entry and that a 64K physical bountry is not crossed unless this
+ // is an Eisa system.
+ //
+
+ if (TranslationEntry != AdapterObject->MapRegisterBase &&
+ (((TranslationEntry - 1)->PhysicalAddress + PAGE_SIZE) !=
+ MapBufferPhysicalAddress || (!eisaSystem &&
+ ((TranslationEntry - 1)->PhysicalAddress & ~0x0ffff) !=
+ (MapBufferPhysicalAddress & ~0x0ffff)))) {
+
+ //
+ // An entry needs to be skipped in the table. This entry will
+ // remain marked as allocated so that no allocation of map
+ // registers will cross this bountry.
+ //
+
+ TranslationEntry++;
+ AdapterObject->NumberOfMapRegisters++;
+ }
+
+ TranslationEntry->VirtualAddress = MapBufferVirtualAddress;
+ TranslationEntry->PhysicalAddress = MapBufferPhysicalAddress;
+ TranslationEntry++;
+ (PCCHAR) MapBufferVirtualAddress += PAGE_SIZE;
+ MapBufferPhysicalAddress += PAGE_SIZE;
+
+ }
+
+ //
+ // Remember the number of pages that where allocated.
+ //
+
+ AdapterObject->NumberOfMapRegisters += NumberOfPages;
+
+ return(TRUE);
+}
+
+PADAPTER_OBJECT
+IopAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID MapRegisterBase
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates and initializes an adapter object to represent an
+ adapter or a DMA controller on the system.
+
+Arguments:
+
+ MapRegistersPerChannel - Specifies the number of map registers that each
+ channel provides for I/O memory mapping.
+
+ AdapterBaseVa - Base virtual address of the adapter itself. If this
+ is NULL then the MasterAdapterObject is allocated.
+
+ MapRegisterBase - Unused.
+
+Return Value:
+
+ The function value is a pointer to the allocate adapter object.
+
+--*/
+
+{
+ PADAPTER_OBJECT AdapterObject;
+ ULONG Size;
+
+ UNREFERENCED_PARAMETER(MapRegisterBase);
+
+ //
+ // Initialize the master adapter if necessary.
+ //
+
+ if (MasterAdapterObject == NULL && (AdapterBaseVa != (PVOID) -1) &&
+ MapRegistersPerChannel) {
+
+ MasterAdapterObject = IopAllocateAdapter(MapRegistersPerChannel,
+ (PVOID) -1,
+ NULL
+ );
+
+ //
+ // If we could not allocate the master adapter then give up.
+ //
+
+ if (MasterAdapterObject == NULL) {
+ return(NULL);
+ }
+ }
+
+ //
+ // Determine the size of the adapter.
+ //
+
+ Size = sizeof( ADAPTER_OBJECT );
+
+ //
+ // Now create the adapter object.
+ //
+
+ AdapterObject = FwAllocatePool(Size);
+
+ //
+ // If the adapter object was successfully created, then attempt to insert
+ // it into the the object table.
+ //
+
+ if (AdapterObject) {
+
+ //
+ // Initialize the adapter object itself.
+ //
+
+ AdapterObject->Type = IO_TYPE_ADAPTER;
+ AdapterObject->Size = Size;
+ AdapterObject->MapRegistersPerChannel = 1;
+ AdapterObject->AdapterBaseVa = AdapterBaseVa;
+
+ if (MapRegistersPerChannel) {
+
+ AdapterObject->MasterAdapter = MasterAdapterObject;
+
+ } else {
+
+ AdapterObject->MasterAdapter = NULL;
+
+ }
+
+ //
+ // If this is the MasterAdapter then initialize the register bit map,
+ // AdapterQueue and the spin lock.
+ //
+
+ if ( AdapterBaseVa == (PVOID) -1 ) {
+
+ AdapterObject->NumberOfMapRegisters = 0;
+ AdapterObject->CommittedMapRegisters = 0;
+ AdapterObject->PagePort = NULL;
+ AdapterObject->AdapterInUse = FALSE;
+
+ //
+ // Allocate the memory map registers. N.B.: FwAllocatePool
+ // returns zeroed memory.
+ //
+
+ AdapterObject->MapRegisterBase = FwAllocatePool(0x2000);
+
+ if ((AdapterObject->MapRegisterBase == NULL) ||
+ (!HalpGrowMapBuffers(AdapterObject, 0x2000))) {
+
+ //
+ // No map registers could be allocated, so take error return.
+ //
+
+ return(NULL);
+
+ }
+ }
+
+ } else {
+
+ //
+ // An error was incurred for some reason. Set the return value
+ // to NULL.
+ //
+
+ return(NULL);
+ }
+
+
+ AdapterObject->MasterDevice = FALSE;
+
+ return AdapterObject;
+}
+
+VOID
+IoFreeMapRegisters(
+ PADAPTER_OBJECT AdapterObject,
+ PVOID MapRegisterBase,
+ ULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine deallocates the map registers for the adapter. If there are
+ any queued adapter waiting for an attempt is made to allocate the next
+ entry.
+
+Arguments:
+
+ AdapterObject - The adapter object to where the map register should be
+ returned.
+
+ MapRegisterBase - The map register base of the registers to be deallocated.
+
+ NumberOfMapRegisters - The number of registers to be deallocated.
+
+Return Value:
+
+ None
+
+--+*/
+
+{
+ PADAPTER_OBJECT MasterAdapter;
+ PTRANSLATION_ENTRY translationEntry;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ if (AdapterObject->MasterAdapter != NULL) {
+ MasterAdapter = AdapterObject->MasterAdapter;
+ } else {
+ MasterAdapter = AdapterObject;
+ }
+
+ //
+ // Determine if this was the last allocation from the adapter. If is was
+ // then free the map registers by restoring the map register base and the
+ // channel count; otherwise the registers are lost. This handles the
+ // normal case.
+ //
+
+ translationEntry = MasterAdapter->MapRegisterBase;
+ translationEntry -= NumberOfMapRegisters;
+
+ if (translationEntry == MapRegisterBase) {
+
+ //
+ // The last allocated registers are being freed.
+ //
+
+ MasterAdapter->MapRegisterBase = (PVOID) translationEntry;
+ AdapterObject->MapRegistersPerChannel += NumberOfMapRegisters;
+ }
+}
+
+VOID
+IoFreeAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to deallocate the specified adapter object.
+ Any map registers that were allocated are also automatically deallocated.
+ No checks are made to ensure that the adapter is really allocated to
+ a device object. However, if it is not, then kernel will bugcheck.
+
+ If another device is waiting in the queue to allocate the adapter object
+ it will be pulled from the queue and its execution routine will be
+ invoked.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object to be deallocated.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ AdapterObject->AdapterInUse = FALSE;
+}
+
+PHYSICAL_ADDRESS
+IoMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN OUT PULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to set up the map registers in the DMA controller
+ to allow a transfer to or from a device.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel that has been allocated.
+
+ Mdl - Pointer to the MDL that describes the pages of memory that are
+ being read or written.
+
+ MapRegisterBase - The address of the base map register that has been
+ allocated to the device driver for use in mapping the transfer.
+
+ CurrentVa - Current virtual address in the buffer described by the MDL
+ that the transfer is being done to or from.
+
+ Length - Supplies the length of the transfer. This determines the
+ number of map registers that need to be written to map the transfer.
+ Returns the length of the transfer which was actually mapped.
+
+ WriteToDevice - Boolean value that indicates whether this is a write
+ to the device from memory (TRUE), or vice versa.
+
+Return Value:
+
+ Returns the logical address to be used by bus masters.
+
+--*/
+
+{
+ BOOLEAN useBuffer;
+ ULONG transferLength;
+ ULONG logicalAddress;
+ ULONG returnAddress;
+ PULONG pageFrame;
+ PUCHAR bytePointer;
+ UCHAR adapterMode;
+ UCHAR dataByte;
+ PTRANSLATION_ENTRY translationEntry;
+ BOOLEAN masterDevice;
+ ULONG pageOffset;
+ BOOLEAN eisaSystem;
+
+ eisaSystem = HalpBusType == MACHINE_TYPE_EISA ? TRUE : FALSE;
+
+ masterDevice = (AdapterObject == NULL) ||
+ (AdapterObject->MasterDevice ? TRUE : FALSE);
+
+ translationEntry = MapRegisterBase;
+ transferLength = *Length;
+ pageOffset = BYTE_OFFSET(CurrentVa);
+
+
+ //
+ // Determine if the data transfer needs to use the map buffer
+ //
+
+ if ((translationEntry) && (!masterDevice) &&
+ (ADDRESS_AND_SIZE_TO_SPAN_PAGES(CurrentVa, transferLength) > 1)) {
+
+ logicalAddress = translationEntry->PhysicalAddress + pageOffset;
+ useBuffer = TRUE;
+
+ } else {
+
+ //
+ // The transfer can only be done for one page
+ //
+
+ transferLength = PAGE_SIZE - pageOffset;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) / PAGE_SIZE;
+ logicalAddress = ((*pageFrame << PAGE_SHIFT) + pageOffset);
+
+ //
+ // If the buffer is contiguous and does not cross a 64K boundary
+ // then just extend the buffer. This restriction does not apply
+ // to eisa systems.
+ //
+
+ while (transferLength < *Length) {
+ if (*pageFrame +1 != *(pageFrame +1) || (!eisaSystem &&
+ *pageFrame & ~0x0f != *(pageFrame + 1) & ~0x0f)) {
+ break;
+ }
+
+ transferLength += PAGE_SIZE;
+ pageFrame ++;
+ }
+
+ transferLength = transferLength > *Length ? *Length : transferLength;
+ useBuffer = FALSE;
+ }
+
+ //
+ // If the logical address is greater than 16Mb, then mapping registers
+ // (buffer xfer) nust be used. This is due to ISA devices only addressing
+ // a max of 16Mb.
+ //
+
+ if (translationEntry && logicalAddress >= MAXIMUM_ISA_PHYSICAL_ADDRESS) {
+
+ logicalAddress = (translationEntry + translationEntry->Index)->
+ PhysicalAddress + pageOffset;
+ useBuffer = TRUE;
+ }
+
+ //
+ // Return the length
+ //
+
+ *Length = transferLength;
+
+ //
+ // Copy the data if necessary
+ //
+
+ if (useBuffer && WriteToDevice) {
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry + translationEntry->Index,
+ CurrentVa,
+ *Length,
+ WriteToDevice
+ );
+
+ }
+
+ //
+ // If there are map registers, update them to reflect the number
+ // used.
+ //
+
+ if (translationEntry) {
+
+ translationEntry->Index += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
+ CurrentVa,
+ transferLength
+ );
+ }
+
+ //
+ // If no adapter was specified, then work is done.
+ //
+ //
+ // We only support 32 bits, but the return is 64. Just
+ // zero extend
+ //
+
+ if (masterDevice) {
+ return(RtlConvertUlongToLargeInteger(logicalAddress));
+ }
+
+ //
+ // Determine the mode based on the trasnfer direction.
+ //
+
+ adapterMode = AdapterObject->AdapterMode;
+ ((PDMA_EISA_MODE) &adapterMode)->TransferType =
+ (UCHAR) (WriteToDevice ? WRITE_TRANSFER : READ_TRANSFER);
+
+ returnAddress = logicalAddress;
+ bytePointer = (PUCHAR) &logicalAddress;
+
+ if (AdapterObject->Width16Bits) {
+
+ //
+ // if this is 16 bit wide, adjust the length and address
+ //
+
+ transferLength >>= 1;
+
+ //
+ // In 16 bit dma mode, the low 16 bits are shifted right one and
+ // the page register value is unchanged. So save the page register
+ // value and shift the logical address then restore the page value.
+ //
+
+ dataByte = bytePointer[2];
+ logicalAddress >>= 1;
+ bytePointer[2] = dataByte;
+
+ }
+
+ //
+ // Determine the controller number based on the adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // A request for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR ( &dmaControl->ClearBytePointer, 0);
+
+ WRITE_PORT_UCHAR ( &dmaControl->Mode, adapterMode);
+
+ WRITE_PORT_UCHAR (
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[0]
+ );
+
+
+ WRITE_PORT_UCHAR (
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[1]
+ );
+
+
+ WRITE_PORT_UCHAR (
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageLowPort)
+ + (ULONG) AdapterObject->PagePort,
+ bytePointer[2]
+ );
+
+ if (eisaSystem) {
+
+ //
+ // Write the high page register with zero. This sets a mode
+ // that allows the page register to be tied with the base count
+ // into a single address register
+ //
+
+ WRITE_PORT_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort)
+ + (ULONG)AdapterObject->PagePort,
+ 0
+ );
+ }
+
+ //
+ // Notify the DMA chip of the length
+ //
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength -1) & 0xff)
+ );
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength -1) >> 8)
+ );
+
+ //
+ // Set the DMA chip to read or write and unmask it
+ //
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+
+ } else {
+
+ //
+ // This is a request for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR ( &dmaControl->ClearBytePointer, 0);
+
+ WRITE_PORT_UCHAR ( &dmaControl->Mode, adapterMode);
+
+ WRITE_PORT_UCHAR (
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[0]
+ );
+
+
+ WRITE_PORT_UCHAR (
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[1]
+ );
+
+
+ WRITE_PORT_UCHAR (
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageLowPort)
+ + (ULONG) AdapterObject->PagePort,
+ bytePointer[2]
+ );
+
+ if (eisaSystem) {
+
+ //
+ // Write the high page register with zero. This sets a mode
+ // that allows the page register to be tied with the base count
+ // into a single address register
+ //
+
+ WRITE_PORT_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort)
+ + (ULONG)AdapterObject->PagePort,
+ 0
+ );
+ }
+
+ //
+ // Notify the DMA chip of the length
+ //
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength -1) & 0xff)
+ );
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength -1) >> 8)
+ );
+
+ //
+ // Set the DMA chip to read or write and unmask it
+ //
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+
+ }
+
+ return(RtlConvertUlongToLargeInteger(returnAddress));
+
+}
+
+BOOLEAN
+IoFlushAdapterBuffers(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine flushes the DMA adapter object buffers. For the Jensen system
+ its clears the enable flag which aborts the dma.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel.
+
+ Mdl - A pointer to a Memory Descriptor List (MDL) that maps the locked-down
+ buffer to/from which the I/O occured.
+
+ MapRegisterBase - A pointer to the base of the map registers in the adapter
+ or DMA controller.
+
+ CurrentVa - The current virtual address in the buffer described the the Mdl
+ where the I/O operation occurred.
+
+ Length - Supplies the length of the transfer.
+
+ WriteToDevice - Supplies a BOOLEAN value that indicates the direction of
+ the data transfer was to the device.
+
+Return Value:
+
+ TRUE - If the transfer was successful.
+
+ FALSE - If there was an error in the transfer.
+
+--*/
+{
+
+ PTRANSLATION_ENTRY translationEntry;
+ PULONG pageFrame;
+ ULONG transferLength;
+ ULONG partialLength;
+ BOOLEAN masterDevice;
+
+ masterDevice = AdapterObject == NULL || AdapterObject->MasterDevice ?
+ TRUE : FALSE;
+
+ translationEntry = MapRegisterBase;
+
+ //
+ // Clear the index of used buffers
+ //
+
+ if (translationEntry) {
+
+ translationEntry->Index = 0;
+
+ }
+
+ //
+ // Determine if the data needs to be copied to the orignal buffer.
+ // This happens if the transfer is from a device, the MapRegisterBase
+ // is not NULL and the xfer spans a page.
+ //
+
+ if (!WriteToDevice && translationEntry) {
+
+ //
+ // if this is not a master device, then just xfer the buffer
+ //
+
+ if (ADDRESS_AND_SIZE_TO_SPAN_PAGES(CurrentVa, Length) > 1 &&
+ !masterDevice) {
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ Length,
+ WriteToDevice
+ );
+
+ } else {
+
+ //
+ // Cycle through the pages of the xfer to determine if there
+ // are any which need to be copied back
+ //
+
+ transferLength = PAGE_SIZE - BYTE_OFFSET(CurrentVa);
+ partialLength = transferLength;
+ pageFrame = (PULONG) (Mdl + 1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) / PAGE_SIZE;
+
+ while (transferLength <= Length) {
+
+ if (*pageFrame >= BYTES_TO_PAGES(MAXIMUM_ISA_PHYSICAL_ADDRESS)) {
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ partialLength,
+ WriteToDevice
+ );
+ }
+
+ (PCCHAR) CurrentVa += partialLength;
+ partialLength = PAGE_SIZE;
+
+ //
+ // Note that transferLength indicates the amount which will be
+ // transfered after the next loop. thus it is updated with the
+ // new partial length.
+ //
+
+ transferLength += partialLength;
+ pageFrame++;
+ translationEntry++;
+ }
+
+ //
+ // Process any remaining residue
+ //
+
+ partialLength = Length - transferLength + partialLength;
+ if (partialLength && *pageFrame >= BYTES_TO_PAGES(MAXIMUM_ISA_PHYSICAL_ADDRESS)) {
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ partialLength,
+ WriteToDevice
+ );
+
+ }
+
+ }
+
+ }
+
+ //
+ // If this is a master device, then there's no more work to do.
+
+ if (masterDevice) {
+
+ return(TRUE);
+
+ }
+
+ //
+ // Mask the DMA request line so that DMA requests are inhibited
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ return(TRUE);
+
+}
+
+PHYSICAL_ADDRESS
+MmGetPhysicalAddress (
+ IN PVOID BaseAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the corresponding physical address for a
+ valid virtual address. I mask out the superpage mode bit, so that
+ what is returned is a real physical address.
+
+Arguments:
+
+ BaseAddress - Supplies the virtual address for which to return the
+ physical address.
+
+Return Value:
+
+ Returns the corresponding physical address.
+
+Environment:
+
+ Kernel mode. Any IRQL level.
+
+--*/
+
+{
+ PHYSICAL_ADDRESS PhysicalAddress;
+
+ PhysicalAddress.HighPart = 0;
+ PhysicalAddress.LowPart = (ULONG)BaseAddress & 0x07fffffff;
+
+ return(PhysicalAddress);
+}
+
+PVOID
+MmAllocateNonCachedMemory (
+ IN ULONG NumberOfBytes
+ )
+
+/*++
+
+Routine Description:
+
+ The MIPS description:
+
+ This function allocates a range of noncached memory in
+ the non-paged portion of the system address space.
+
+ This routine is designed to be used by a driver's initialization
+ routine to allocate a noncached block of virtual memory for
+ various device specific buffers.
+
+ The Alpha description:
+
+ Since Alpha data caches are kept coherent with DMA, this just
+ allocates a section of memory for the caller. It may be in the
+ cache.
+
+
+Arguments:
+
+ NumberOfBytes - Supplies the number of bytes to allocate.
+
+Return Value:
+
+ NULL - the specified request could not be satisfied.
+
+ NON-NULL - Returns a pointer (virtual address in the nonpaged portion
+ of the system) to the allocated physically contiguous
+ memory.
+
+Environment:
+
+ Kernel mode, IRQL of APC_LEVEL or below.
+
+--*/
+
+{
+ return (FwAllocatePool(NumberOfBytes));
+}
+
+PVOID
+MmMapIoSpace (
+ IN PHYSICAL_ADDRESS PhysicalAddress,
+ IN ULONG NumberOfBytes,
+ IN BOOLEAN CacheEnable
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the corresponding virtual address for a
+ known physical I/O address.
+
+Arguments:
+
+ PhysicalAddress - Supplies the physical address.
+
+ NumberOfBytes - Unused.
+
+ CacheEnable - Unused.
+
+Return Value:
+
+ Returns the corresponding meta-virtual address.
+
+Environment:
+
+ Kernel mode. Any IRQL level.
+
+--*/
+
+{
+
+//
+// For ISA machines, this routine should be null.
+//
+
+#ifdef EISA_PLATFORM
+
+ PCCHAR VirtualAddress;
+
+ //
+ // switch on bits <33:32> of the physical address
+ //
+
+ switch (PhysicalAddress.HighPart & 3) {
+
+ case 0: /* memory space, this is an error. */
+ return(NULL);
+ break;
+
+ case 1: /* "Combo" space */
+ VirtualAddress =
+ (PVOID)
+ (COMBO_QVA |
+ 0x800000 |
+ ((PhysicalAddress.LowPart >> COMBO_BIT_SHIFT) &
+ 0x7fffff)
+ );
+ break;
+
+ case 2: /* EISA memory space */
+ VirtualAddress =
+ (PVOID)
+ (EISA_QVA |
+ 0x0000000 |
+ ((PhysicalAddress.LowPart >> EISA_BIT_SHIFT) &
+ 0x1ffffff)
+ );
+ break;
+
+ case 3: /* EISA I/O space */
+ VirtualAddress =
+ (PVOID)
+ (EISA_QVA |
+ 0x8000000 |
+ ((PhysicalAddress.LowPart >> EISA_BIT_SHIFT) &
+ 0x1ffffff)
+ );
+ break;
+
+ }
+
+ return(VirtualAddress);
+
+#endif // EISA_PLATFORM
+
+ }
diff --git a/private/ntos/fw/alpha/jxkbd.c b/private/ntos/fw/alpha/jxkbd.c
new file mode 100644
index 000000000..11ced6d5b
--- /dev/null
+++ b/private/ntos/fw/alpha/jxkbd.c
@@ -0,0 +1,581 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ jxkbd.c
+
+Abstract:
+
+ This module implements the keyboard boot driver for the Jazz system.
+
+Author:
+
+ David M. Robinson (davidro) 8-Aug-1991
+
+Environment:
+
+ Kernel mode.
+
+
+Revision History:
+
+
+ 26-May-1992 John DeRosa [DEC]
+
+ Added Alpha/Jensen hooks. The Jensen firmware does not use any
+ interrupts. Additional keyboard changes are in fwsignal.c.
+
+--*/
+
+#include "fwp.h"
+#include "iodevice.h"
+#include "string.h"
+#include "xxstring.h"
+
+ARC_STATUS
+KeyboardClose (
+ IN ULONG FileId
+ );
+
+ARC_STATUS
+KeyboardMount (
+ IN PCHAR MountPath,
+ IN MOUNT_OPERATION Operation
+ );
+
+ARC_STATUS
+KeyboardOpen (
+ IN PCHAR OpenPath,
+ IN OPEN_MODE OpenMode,
+ IN OUT PULONG FileId
+ );
+
+ARC_STATUS
+KeyboardRead (
+ IN ULONG FileId,
+ IN PVOID Buffer,
+ IN ULONG Length,
+ OUT PULONG Count
+ );
+
+ARC_STATUS
+KeyboardGetReadStatus (
+ IN ULONG FileId
+ );
+
+ARC_STATUS
+KeyboardSeek (
+ IN ULONG FileId,
+ IN PLARGE_INTEGER Offset,
+ IN SEEK_MODE SeekMode
+ );
+
+ARC_STATUS
+KeyboardWrite (
+ IN ULONG FileId,
+ IN PVOID Buffer,
+ IN ULONG Length,
+ OUT PULONG Count
+ );
+
+ARC_STATUS
+KeyboardGetFileInformation (
+ IN ULONG FileId,
+ OUT PFILE_INFORMATION Finfo
+ );
+
+//
+// Define static data.
+//
+BL_DEVICE_ENTRY_TABLE KeyboardEntryTable = {
+ KeyboardClose,
+ KeyboardMount,
+ KeyboardOpen,
+ KeyboardRead,
+ KeyboardGetReadStatus,
+ KeyboardSeek,
+ KeyboardWrite,
+ KeyboardGetFileInformation,
+ (PARC_SET_FILE_INFO_ROUTINE)NULL
+ };
+
+KEYBOARD_BUFFER KbdBuffer;
+
+BOOLEAN FwLeftShift;
+BOOLEAN FwRightShift;
+BOOLEAN FwControl;
+BOOLEAN FwAlt;
+BOOLEAN FwCapsLock;
+
+
+//
+// Define prototypes for all routines used by this module.
+//
+
+UCHAR
+FwInputScanCode(
+ VOID
+ );
+
+
+ARC_STATUS
+KeyboardGetFileInformation (
+ IN ULONG FileId,
+ OUT PFILE_INFORMATION Finfo
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns EINVAL as no FileInformation can be
+ returned for the Keyboard driver.
+
+Arguments:
+
+ The arguments are not used.
+
+Return Value:
+
+ EINVAL is returned
+
+--*/
+
+{
+ return EINVAL;
+}
+
+
+ARC_STATUS
+KeyboardClose (
+ IN ULONG FileId
+ )
+
+/*++
+
+Routine Description:
+
+ This function closes the file table entry specified by the file id.
+
+Arguments:
+
+ FileId - Supplies the file table index.
+
+Return Value:
+
+ ESUCCESS is returned
+
+--*/
+
+{
+
+ BlFileTable[FileId].Flags.Open = 0;
+ return ESUCCESS;
+}
+
+ARC_STATUS
+KeyboardMount (
+ IN PCHAR MountPath,
+ IN MOUNT_OPERATION Operation
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ return EINVAL;
+}
+
+ARC_STATUS
+KeyboardOpen (
+ IN PCHAR OpenPath,
+ IN OPEN_MODE OpenMode,
+ IN OUT PULONG FileId
+ )
+/*++
+
+Routine Description:
+
+ This is the open routine for the Keyboard device.
+
+Arguments:
+
+ OpenPath - Supplies the pathname of the device to open.
+
+ OpenMode - Supplies the mode (read only, write only, or read write).
+
+ FileId - Supplies a free file identifier to use. If the device is already
+ open this parameter can be used to return the file identifier
+ already in use.
+
+Return Value:
+
+ If the open was successful, ESUCCESS is returned, otherwise an error code
+ is returned.
+
+--*/
+{
+ PCONSOLE_CONTEXT Context;
+
+ Context = &BlFileTable[*FileId].u.ConsoleContext;
+ if ( strstr(OpenPath, ")console(1)" ) != NULL ) {
+ Context->ConsoleNumber = 1;
+ } else {
+ Context->ConsoleNumber = 0;
+ }
+ return ESUCCESS;
+}
+
+ARC_STATUS
+KeyboardRead (
+ IN ULONG FileId,
+ IN PVOID Buffer,
+ IN ULONG Length,
+ OUT PULONG Count
+ )
+/*++
+
+Routine Description:
+
+ This routine reads keys from the keyboard and passes along either ascii
+ or Unicode characters to the caller.
+
+ In Alpha/Jensen, the polling is done in the FwInputScanCode() function.
+
+
+Arguments:
+
+ FileId - Supplies a file id.
+
+ Buffer - Supplies a pointer to a buffer to receive the characters.
+
+ Length - Supplies the length of Buffer in bytes.
+
+ Count - Returns the count of the bytes that were received.
+
+Return Value:
+
+ A value of ESUCCESS is returned.
+
+--*/
+{
+ PCHAR OutputBuffer;
+ PCONSOLE_CONTEXT Context;
+ BOOLEAN Unicode;
+
+ OutputBuffer = (PCHAR)Buffer;
+ Context = &BlFileTable[FileId].u.ConsoleContext;
+
+ if (Context->ConsoleNumber == 1) {
+ if (Length & 1) {
+
+ //
+ // Length is not an even number of bytes, return an error.
+ //
+
+ return(EINVAL);
+ }
+ Unicode = TRUE;
+ } else {
+ Unicode = FALSE;
+ }
+
+ *Count = 0;
+ while (*Count < Length) {
+ *OutputBuffer++ = FwInputScanCode();
+ (*Count)++;
+ if (Unicode) {
+ *OutputBuffer++ = 0;
+ (*Count)++;
+ }
+ }
+ return ESUCCESS;
+}
+
+
+ARC_STATUS
+KeyboardGetReadStatus (
+ IN ULONG FileId
+ )
+/*++
+
+Routine Description:
+
+ This routine checks to see if a character is available from the keyboard.
+
+Arguments:
+
+ FileId - Supplies a file identifier.
+
+Return Value:
+
+ Returns ESUCCESS is a byte is available, otherwise EAGAIN is returned.
+
+--*/
+{
+
+#ifndef ALPHA
+
+ if (KbdBuffer.ReadIndex == KbdBuffer.WriteIndex) {
+ return EAGAIN;
+ } else {
+ return ESUCCESS;
+ }
+
+#else
+
+ //
+ // Alpha does polling.
+ //
+
+ if (KbdBuffer.ReadIndex != KbdBuffer.WriteIndex) {
+
+ // A character is available
+ return ESUCCESS;
+
+ } else if (READ_PORT_UCHAR((PUCHAR)&KEYBOARD_READ->Status) & KBD_OBF_MASK) {
+
+ // A character is available at the keyboard, but it may be a
+ // character that is not returned to the calling program (e.g., a
+ // break code). Screen it here.
+
+ TranslateScanCode(READ_PORT_UCHAR((PUCHAR)&KEYBOARD_READ->Data));
+ if (KbdBuffer.ReadIndex != KbdBuffer.WriteIndex) {
+ // A character is now available
+ return ESUCCESS;
+ } else {
+ // A character is not available, let the user drain any other
+ // characters or non-characters by calling this again.
+ return EAGAIN;
+ }
+
+ } else {
+
+ // A character is not available
+ return EAGAIN;
+
+ }
+
+#endif
+
+}
+
+ARC_STATUS
+KeyboardWrite (
+ IN ULONG FileId,
+ IN PVOID Buffer,
+ IN ULONG Length,
+ OUT PULONG Count
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+ ESUCCESS is returned.
+
+--*/
+
+{
+ return ESUCCESS;
+}
+
+ARC_STATUS
+KeyboardSeek (
+ IN ULONG FileId,
+ IN PLARGE_INTEGER Offset,
+ IN SEEK_MODE SeekMode
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+ ESUCCESS is returned.
+
+--*/
+
+{
+ return ESUCCESS;
+}
+
+VOID
+KeyboardInitialize (
+ IN OUT PDRIVER_LOOKUP_ENTRY LookupTableEntry,
+ IN ULONG Entries
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the keyboard control registers, clears the
+ fifo, and initializes the keyboard entry in the driver lookup table.
+
+Arguments:
+
+ LookupTableEntry - Supplies a pointer to the first free location in the
+ driver lookup table.
+
+ Entries - Supplies the number of free entries in the driver lookup table.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR Byte;
+
+ //
+ // Initialize the driver lookup table.
+ //
+
+ LookupTableEntry->DevicePath = FW_KEYBOARD_IN_DEVICE_PATH;
+ LookupTableEntry->DispatchTable = &KeyboardEntryTable;
+
+ //
+ // Initialize static data.
+ //
+
+ FwLeftShift = FALSE;
+ FwRightShift = FALSE;
+ FwControl = FALSE;
+ FwAlt = FALSE;
+ FwCapsLock = FALSE;
+
+ KbdBuffer.ReadIndex = KbdBuffer.WriteIndex = 0;
+
+ //
+ // Call the selftest keyboard initialization routine. If the keyboard
+ // is OK, enable interrupts.
+ //
+
+ if (!InitKeyboard()) {
+
+ //
+ // Enable kbd interrupts in the keyboard controller.
+ //
+ SendKbdCommand(KBD_CTR_READ_COMMAND);
+ GetKbdData(&Byte,100);
+
+ //
+ // Clear translation mode and enable Kbd interrupt.
+ //
+ Byte = (Byte & 0xBF) | KbdCommandEnableKbdInt;
+ SendKbdCommand(KBD_CTR_WRITE_COMMAND);
+ SendKbdData(Byte);
+
+#ifndef ALPHA
+ //
+ // Not needed for Alpha.
+ //
+ //
+ // Enable keyboard interrupts in the interrupt enable register.
+ //
+ WRITE_PORT_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Enable,
+ (1 << (KEYBOARD_VECTOR - DEVICE_VECTORS - 1)));
+#endif
+
+
+ }
+
+ return;
+}
+
+UCHAR
+FwInputScanCode (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads a byte from the keyboard. If no data is available,
+ it blocks until a key is typed.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns the character read from the keyboard.
+
+--*/
+
+{
+
+#ifndef ALPHA
+
+ UCHAR ScanCode;
+
+ while (KbdBuffer.ReadIndex == KbdBuffer.WriteIndex) {
+ }
+ KbdBuffer.ReadIndex = (KbdBuffer.ReadIndex+1) % KBD_BUFFER_SIZE;
+ ScanCode = KbdBuffer.Buffer[KbdBuffer.ReadIndex];
+
+ return ScanCode;
+
+#else
+
+ //
+ // Alpha. If there are remaining characters in the
+ // circular buffer, return the next one. Otherwise,
+ // hang until another character is typed and then call
+ // TranslateScanCode. Then return a character.
+ //
+
+ while (TRUE) {
+
+ if (KbdBuffer.ReadIndex != KbdBuffer.WriteIndex) {
+
+ //
+ // A character is in the buffer. Return it.
+ //
+
+ KbdBuffer.ReadIndex = (KbdBuffer.ReadIndex+1) % KBD_BUFFER_SIZE;
+ return (KbdBuffer.Buffer[KbdBuffer.ReadIndex]);
+ }
+
+
+ //
+ // Wait until a character is typed, then scan it, and loop back.
+ // The TranslateScanCode() calls will eventually bump the KbdBuffer
+ // WriteIndex.
+ //
+
+ while ((READ_PORT_UCHAR((PUCHAR)&KEYBOARD_READ->Status) &
+ KBD_OBF_MASK) == 0) {
+ }
+
+ TranslateScanCode(READ_PORT_UCHAR((PUCHAR)&KEYBOARD_READ->Data));
+ FwStallExecution(10); // Don't pound on the controller.
+ }
+
+#endif
+
+}
diff --git a/private/ntos/fw/alpha/jxreboot.c b/private/ntos/fw/alpha/jxreboot.c
new file mode 100644
index 000000000..5e17f0932
--- /dev/null
+++ b/private/ntos/fw/alpha/jxreboot.c
@@ -0,0 +1,157 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ jxreboot.c
+
+Abstract:
+
+ This module contains the Firmware Termination Functions.
+
+Author:
+
+ Lluis Abello (lluis) 4-Sep-1991
+
+
+Revision History:
+
+ 11-June-1992 John DeRosa [DEC]
+
+ Added Alpha/Jensen modifications.
+
+--*/
+#include "fwp.h"
+#include "fwstring.h"
+
+
+VOID
+ResetSystem (
+ IN VOID
+ )
+/*++
+
+Routine Description:
+
+ This effectively resets the system by restarting the firmware
+ at the beginning of the firmware PALcode.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ AlphaInstHalt();
+}
+
+VOID
+FwRestart(
+ IN VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine implements the Firmware Restart termination function.
+ It generates a soft reset to the system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Does not return to the caller.
+
+--*/
+{
+ ResetSystem();
+}
+
+VOID
+FwReboot(
+ IN VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine implements the Firmware Reboot termination function.
+ It generates a soft reset to the system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Does not return to the caller.
+
+--*/
+{
+ ResetSystem();
+}
+
+VOID
+FwEnterInteractiveMode(
+ IN VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine implements the Firmware EnterInteractiveMode function.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ FwMonitor(3);
+ return;
+}
+
+VOID
+FwTerminationInitialize(
+ IN VOID
+ )
+
+/*++
+
+Routine Description:
+
+ //
+ // Initialize the termination function entry points in the transfer vector
+ //
+ This routine initializes the termination function entry points
+ in the transfer vector.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ (PARC_HALT_ROUTINE)SYSTEM_BLOCK->FirmwareVector[HaltRoutine] = FwHalt;
+ (PARC_POWERDOWN_ROUTINE)SYSTEM_BLOCK->FirmwareVector[PowerDownRoutine] = FwHalt;
+ (PARC_RESTART_ROUTINE)SYSTEM_BLOCK->FirmwareVector[RestartRoutine] = FwRestart;
+ (PARC_REBOOT_ROUTINE)SYSTEM_BLOCK->FirmwareVector[RebootRoutine] = FwReboot;
+ (PARC_INTERACTIVE_MODE_ROUTINE)SYSTEM_BLOCK->FirmwareVector[InteractiveModeRoutine] = FwEnterInteractiveMode;
+// (PARC_RETURN_FROM_MAIN_ROUTINE)SYSTEM_BLOCK->FirmwareVector[ReturnFromMainRoutine] = FwReturnFromMain;
+}
diff --git a/private/ntos/fw/alpha/jxserial.c b/private/ntos/fw/alpha/jxserial.c
new file mode 100644
index 000000000..c6c8fbcf8
--- /dev/null
+++ b/private/ntos/fw/alpha/jxserial.c
@@ -0,0 +1,590 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ jxserial.c
+
+Abstract:
+
+ This module implements the serila boot driver for the Jazz system.
+
+Author:
+
+ Lluis Abello (lluis) 9-Aug-1991
+
+Environment:
+
+ Kernel mode.
+
+
+Revision History:
+
+ 30-April-1992 John DeRosa [DEC]
+
+ Added Alpha/Jensen modifications.
+
+--*/
+
+#include "fwp.h"
+
+#ifdef JENSEN
+#include "jnsnserp.h"
+#else
+#include "mrgnserp.h" // morgan
+#endif
+
+#include "xxstring.h"
+
+ARC_STATUS
+SerialClose (
+ IN ULONG FileId
+ );
+
+ARC_STATUS
+SerialMount (
+ IN PCHAR MountPath,
+ IN MOUNT_OPERATION Operation
+ );
+
+ARC_STATUS
+SerialOpen (
+ IN PCHAR OpenPath,
+ IN OPEN_MODE OpenMode,
+ IN OUT PULONG FileId
+ );
+
+ARC_STATUS
+SerialRead (
+ IN ULONG FileId,
+ IN PVOID Buffer,
+ IN ULONG Length,
+ OUT PULONG Count
+ );
+
+ARC_STATUS
+SerialGetReadStatus (
+ IN ULONG FileId
+ );
+
+ARC_STATUS
+SerialSeek (
+ IN ULONG FileId,
+ IN PLARGE_INTEGER Offset,
+ IN SEEK_MODE SeekMode
+ );
+
+ARC_STATUS
+SerialWrite (
+ IN ULONG FileId,
+ IN PVOID Buffer,
+ IN ULONG Length,
+ OUT PULONG Count
+ );
+
+ARC_STATUS
+SerialGetFileInformation (
+ IN ULONG FileId,
+ OUT PFILE_INFORMATION Finfo
+ );
+//
+// Declare and initialize the Serial entry table.
+//
+BL_DEVICE_ENTRY_TABLE SerialEntryTable = {
+ SerialClose,
+ SerialMount,
+ SerialOpen,
+ SerialRead,
+ SerialGetReadStatus,
+ SerialSeek,
+ SerialWrite,
+ SerialGetFileInformation,
+ (PARC_SET_FILE_INFO_ROUTINE)NULL
+ };
+
+
+#define SP_BASE(Fid) PSP_WRITE_REGISTERS SP; \
+ SP = (PSP_WRITE_REGISTERS)BlFileTable[Fid].u.SerialContext.PortBase
+//
+// Define function prototypes
+//
+
+VOID
+SerialBootSetup(
+ IN ULONG FileId
+ );
+
+ARC_STATUS
+SerialGetFileInformation (
+ IN ULONG FileId,
+ OUT PFILE_INFORMATION Finfo
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns EINVAL as no FileInformation can be
+ returned for the Serial line driver.
+
+Arguments:
+
+ The arguments are not used.
+
+Return Value:
+
+ EINVAL is returned
+
+--*/
+
+{
+ return EINVAL;
+}
+
+ARC_STATUS
+SerialClose (
+ IN ULONG FileId
+ )
+
+/*++
+
+Routine Description:
+
+ This function closes the file table entry specified by the file id.
+
+Arguments:
+
+ FileId - Supplies the file table index.
+
+Return Value:
+
+ ESUCCESS is returned.
+
+--*/
+
+{
+ BlFileTable[FileId].Flags.Open = 0;
+ return ESUCCESS;
+}
+
+ARC_STATUS
+SerialBootWrite(
+ CHAR Char,
+ ULONG SP
+ )
+/*++
+
+Routine Description:
+
+ This routine writes a character to the serial port.
+
+Arguments:
+
+ Char - Character to write.
+
+ SP - Base address of the serial port.
+
+Return Value:
+
+ If the operation is performed without errors, ESUCCESS is returned,
+ otherwise an error code is returned.
+
+--*/
+{
+ UCHAR DataByte;
+
+ //
+ // wait for transmitter holding register to be empty
+ //
+ do {
+ DataByte=READ_PORT_UCHAR(&((PSP_READ_REGISTERS)SP)->LineStatus);
+ } while (((PSP_LINE_STATUS)(&DataByte))->TransmitHoldingEmpty == 0);
+
+ //
+ // transmit character
+ //
+ WRITE_PORT_UCHAR(&((PSP_WRITE_REGISTERS)SP)->TransmitBuffer,Char);
+ return ESUCCESS;
+}
+ARC_STATUS
+SerialWrite (
+ IN ULONG FileId,
+ IN PVOID Buffer,
+ IN ULONG Length,
+ OUT PULONG Count
+ )
+/*++
+
+Routine Description:
+
+ This routine implements the write operation for the ARC firmware
+ serial port driver.
+
+Arguments:
+
+ FileId - Supplies a file id.
+
+ Buffer - Supplies a pointer to a buffer containing the characters to
+ write to the serial port.
+
+ Length - Supplies the length of Buffer.
+
+ Count - Returns the count of the characters that were written.
+
+Return Value:
+
+ If the operation is performed without errors, ESUCCESS is returned,
+ otherwise an error code is returned.
+
+--*/
+{
+ ARC_STATUS Status;
+
+ for (*Count=0; *Count < Length; (*Count)++) {
+ if (Status=SerialBootWrite(*(PCHAR)Buffer,
+ BlFileTable[FileId].u.SerialContext.PortBase)
+ ) {
+ return Status;
+ }
+ ((PCHAR)Buffer)++;
+ }
+ return ESUCCESS;
+}
+
+ARC_STATUS
+SerialRead (
+ IN ULONG FileId,
+ IN PVOID Buffer,
+ IN ULONG Length,
+ OUT PULONG Count
+ )
+
+/*++
+
+Routine Description:
+
+ This routine implements the read operation for the ARC firmware
+ serial port driver.
+
+Arguments:
+
+ FileId - Supplies a file id.
+
+ Buffer - Supplies a pointer to a buffer where the characters read
+ from the serial port will be stored.
+
+ Length - Supplies the length of Buffer.
+
+ Count - Returns the count of the characters that were read.
+
+Return Value:
+
+ If the operation is performed without errors, ESUCCESS is returned,
+ otherwise an error code is returned.
+
+--*/
+{
+ UCHAR DataByte;
+ SP_BASE(FileId);
+ for (*Count=0; *Count < Length; (*Count)++) {
+ //
+ // if no characters are available, then set data terminal ready
+ // and continue polling.
+ //
+ DataByte = READ_PORT_UCHAR(&((PSP_READ_REGISTERS)SP)->LineStatus);
+ if ((((PSP_LINE_STATUS)(&DataByte))->DataReady == 0)) {
+ DataByte=0;
+ ((PSP_MODEM_CONTROL)(&DataByte))->DataTerminalReady=1;
+ ((PSP_MODEM_CONTROL)(&DataByte))->Interrupt=1;
+ WRITE_PORT_UCHAR(&SP->ModemControl,DataByte);
+ }
+ //
+ // Poll until a character is available from the serial port
+ //
+ do {
+ DataByte=READ_PORT_UCHAR(&((PSP_READ_REGISTERS)SP)->LineStatus);
+ } while ((((PSP_LINE_STATUS)(&DataByte))->DataReady == 0));
+
+ //
+ // turn off data terminal ready
+ //
+ DataByte=0;
+ ((PSP_MODEM_CONTROL)(&DataByte))->Interrupt=1;
+ WRITE_PORT_UCHAR(&SP->ModemControl,DataByte);
+
+ //
+ // Read character
+ //
+ *(PCHAR)Buffer = READ_PORT_UCHAR(&((PSP_READ_REGISTERS)SP)->ReceiveBuffer);
+ ((PCHAR)Buffer)++;
+ }
+ return ESUCCESS;
+}
+
+
+ARC_STATUS
+SerialOpen (
+ IN PCHAR OpenPath,
+ IN OPEN_MODE OpenMode,
+ IN OUT PULONG FileId
+ )
+
+/*++
+
+Routine Description:
+
+ This routine opens the specified serial port.
+
+Arguments:
+
+ OpenPath - Supplies the pathname of the device to open.
+
+ OpenMode - Supplies the mode (read only, write only, or read write).
+
+ FileId - Supplies a free file identifier to use. If the device is already
+ open this parameter can be used to return the file identifier
+ already in use.
+
+Return Value:
+
+ If the open was successful, ESUCCESS is returned, otherwise an error code
+ is returned.
+
+--*/
+
+{
+ ULONG Port;
+
+ //
+ // Check for the serial port to open 0,1
+ //
+ if (JzGetPathMnemonicKey(OpenPath,
+ "serial",
+ &Port
+ )) {
+ return ENODEV;
+ }
+
+ //
+ // Init file table
+ //
+ switch (Port) {
+
+ case 0: // serial port 0, which is com port 1
+
+ BlFileTable[*FileId].u.SerialContext.PortNumber = 0;
+ BlFileTable[*FileId].u.SerialContext.PortBase = COMPORT1_VIRTUAL_BASE;
+ break;
+
+ case 1: // serial port 1, which is com port 2
+
+ BlFileTable[*FileId].u.SerialContext.PortNumber = 1;
+ BlFileTable[*FileId].u.SerialContext.PortBase = COMPORT2_VIRTUAL_BASE;
+ break;
+
+ default:
+ return EIO;
+ }
+
+ //
+ // Initialize the serial port.
+ //
+ SerialBootSetup(BlFileTable[*FileId].u.SerialContext.PortBase);
+ return ESUCCESS;
+}
+
+VOID
+SerialBootSetup(
+ IN ULONG SP
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the serial port controller.
+
+Arguments:
+
+ SP - Supplies the virtual address of the serial port.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ UCHAR Trash;
+ UCHAR DataByte;
+ //
+ // Clear the divisor latch, clear all interrupt enables, and reset and
+ // disable the FIFO's.
+ //
+
+ WRITE_PORT_UCHAR(&((PSP_WRITE_REGISTERS)SP)->LineControl, 0x0);
+ WRITE_PORT_UCHAR(&((PSP_WRITE_REGISTERS)SP)->InterruptEnable, 0x0);
+ DataByte = 0;
+
+#if 0
+//
+// Unused Jazz code. Jensen doesn't have FIFO controls.
+//
+ ((PSP_FIFO_CONTROL)(&DataByte))->ReceiveFifoReset = 1;
+ ((PSP_FIFO_CONTROL)(&DataByte))->TransmitFifoReset = 1;
+ WRITE_PORT_UCHAR(&((PSP_WRITE_REGISTERS)SP)->FifoControl, DataByte);
+#endif
+
+ //
+ // Set the divisor latch and set the baud rate to 9600 baud.
+ //
+
+ DataByte = 0;
+ ((PSP_LINE_CONTROL)(&DataByte))->DivisorLatch = 1;
+ WRITE_PORT_UCHAR(&((PSP_WRITE_REGISTERS)SP)->LineControl, DataByte);
+ WRITE_PORT_UCHAR(&((PSP_WRITE_REGISTERS)SP)->TransmitBuffer, BAUD_RATE_9600);
+// WRITE_PORT_UCHAR(&((PSP_WRITE_REGISTERS)SP)->TransmitBuffer, BAUD_RATE_19200);
+ WRITE_PORT_UCHAR(&((PSP_WRITE_REGISTERS)SP)->InterruptEnable, 0x0);
+
+ //
+ // Clear the divisor latch and set the character size to eight bits
+ // with one stop bit and no parity checking.
+ //
+
+ DataByte = 0;
+ ((PSP_LINE_CONTROL)(&DataByte))->CharacterSize = EIGHT_BITS;
+ WRITE_PORT_UCHAR(&((PSP_WRITE_REGISTERS)SP)->LineControl, DataByte);
+
+ //
+ // Set data terminal ready and request to send.
+ // And open interrupt tristate line
+ //
+
+ DataByte = 0;
+ ((PSP_MODEM_CONTROL)(&DataByte))->DataTerminalReady = 1;
+ ((PSP_MODEM_CONTROL)(&DataByte))->RequestToSend = 1;
+ ((PSP_MODEM_CONTROL)(&DataByte))->Interrupt=1;
+ WRITE_PORT_UCHAR(&((PSP_WRITE_REGISTERS)SP)->ModemControl, DataByte);
+
+ Trash = READ_PORT_UCHAR(&((PSP_READ_REGISTERS)SP)->LineStatus);
+ Trash = READ_PORT_UCHAR(&((PSP_READ_REGISTERS)SP)->ReceiveBuffer);
+}
+
+ARC_STATUS
+SerialGetReadStatus (
+ IN ULONG FileId
+ )
+/*++
+
+Routine Description:
+
+ This routine checks to see if a character is available from the serial line.
+
+Arguments:
+
+ FileId - Supplies a file identifier.
+
+Return Value:
+
+ Returns ESUCCESS is a byte is available, otherwise EAGAIN is returned.
+
+--*/
+{
+ UCHAR DataByte;
+ SP_BASE(FileId);
+ DataByte = READ_PORT_UCHAR(&((PSP_READ_REGISTERS)SP)->LineStatus);
+ if ((((PSP_LINE_STATUS)(&DataByte))->DataReady == 0)) {
+ return EAGAIN;
+ }
+ return ESUCCESS;
+}
+
+ARC_STATUS
+SerialMount (
+ IN PCHAR MountPath,
+ IN MOUNT_OPERATION Operation
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ return EINVAL;
+}
+
+ARC_STATUS
+SerialSeek (
+ IN ULONG FileId,
+ IN IN PLARGE_INTEGER Offset,
+ IN SEEK_MODE SeekMode
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+ ESUCCESS is returned.
+
+--*/
+
+{
+ return ESUCCESS;
+}
+
+VOID
+SerialInitialize(
+ IN OUT PDRIVER_LOOKUP_ENTRY LookupTableEntry,
+ IN ULONG Entries
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the serial device dispatch table
+ and the entries in the driver lookup table.
+
+Arguments:
+
+ LookupTableEntry - Supplies a pointer to the first free location in the
+ driver lookup table.
+
+ Entries - Supplies the number of free entries in the driver lookup table.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+
+ //
+ // Initialize the driver lookup table, and increment the pointer.
+ //
+
+ LookupTableEntry->DevicePath = FW_SERIAL_0_DEVICE;
+ LookupTableEntry->DispatchTable = &SerialEntryTable;
+
+ if (Entries>1) {
+ LookupTableEntry++;
+ LookupTableEntry->DevicePath = FW_SERIAL_1_DEVICE;
+ LookupTableEntry->DispatchTable = &SerialEntryTable;
+ }
+}
diff --git a/private/ntos/fw/alpha/jxsysid.c b/private/ntos/fw/alpha/jxsysid.c
new file mode 100644
index 000000000..3acd7c882
--- /dev/null
+++ b/private/ntos/fw/alpha/jxsysid.c
@@ -0,0 +1,168 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ jxsysid.c
+
+Abstract:
+
+ This module implements the ARC firmware System ID Query functions as
+ described in the Advanced Risc Computing Specification (Revision 1.00),
+ section 3.3.3.5, for a MIPS R3000 or R4000 Jazz system.
+
+Author:
+
+ David M. Robinson (davidro) 11-July-1991
+
+
+Revision History:
+
+ 26-May-1992 John DeRosa [DEC]
+
+ Added Alpha/Jensen hooks.
+
+ 31-March-1993 Bruce Butts [DEC]
+
+ Added Alpha/Morgan hooks.
+
+--*/
+
+#include "fwp.h"
+
+//
+// Define the system identifier.
+//
+
+SYSTEM_ID SystemId;
+
+extern ULONG SystemRevisionId;
+
+VOID
+FwSystemIdInitialize (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the system identifer routine address.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ //
+ // Initialize the system identifier routine address in the system
+ // parameter block.
+ //
+
+ (PARC_GET_SYSTEM_ID_ROUTINE)SYSTEM_BLOCK->FirmwareVector[GetSystemIdRoutine] =
+ FwGetSystemId;
+
+ (PARC_FLUSH_ALL_CACHES_ROUTINE)SYSTEM_BLOCK->FirmwareVector[FlushAllCachesRoutine] =
+ FwFlushAllCaches;
+
+ return;
+}
+
+
+PSYSTEM_ID
+FwGetSystemId (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system ID, which consists of an eight byte
+ VendorId and an eight byte ProductId.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns a pointer to a buffer containing the system id structure.
+
+--*/
+
+{
+ UCHAR TempString[10];
+
+ //
+ // There is no unique identification of each Jensen, so we can
+ // load up the SystemId variable directly.
+ //
+
+ strncpy((PCHAR)&SystemId.VendorId, "Digital", 8);
+
+#ifdef JENSEN
+ sprintf(TempString, "%d0Jensen", SystemRevisionId);
+#endif // JENSEN
+
+#ifdef MORGAN
+ sprintf(TempString, "%d0Morgan", SystemRevisionId);
+#endif // MORGAN
+
+ strncpy((PCHAR)&SystemId.ProductId, TempString, 8);
+
+ return &SystemId;
+}
+
+
+VOID
+FwFlushAllCaches (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ TEMPTEMP Fix this up soon!!
+Arguments:
+
+ None.
+
+Return Value:
+
+
+--*/
+
+{
+
+#ifndef _ALPHA_
+
+ HalSweepIcache();
+ HalSweepDcache();
+
+#else
+
+ // Alpha code
+
+ //
+ // The functional definition of this function is nowhere to be found. For
+ // safety, we issue two MB's (so the EV4 write buffers are purged,
+ // and not just serialized) and one IMB.
+ //
+
+ AlphaInstIMB();
+ AlphaInstMB();
+ AlphaInstMB();
+
+#endif
+
+ return;
+}
diff --git a/private/ntos/fw/alpha/jxvendor.c b/private/ntos/fw/alpha/jxvendor.c
new file mode 100644
index 000000000..1e3f7dd7a
--- /dev/null
+++ b/private/ntos/fw/alpha/jxvendor.c
@@ -0,0 +1,750 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ jxvendor.c
+
+Abstract:
+
+ Implementation of the vendor private routines for the Jazz ARC firmware.
+
+Author:
+
+ David M. Robinson (davidro) 13-June-1991
+
+
+Revision History:
+
+ 26-May-1992 John DeRosa [DEC]
+
+ Added Alpha/Jensen hooks.
+
+--*/
+
+#include "fwp.h"
+
+//
+// Routine prototypes.
+//
+
+PVOID
+FwAllocatePool(
+ IN ULONG NumberOfBytes
+ );
+
+VOID
+FwStallExecution (
+ IN ULONG MicroSeconds
+ );
+
+//
+// Static Variables
+//
+
+PCHAR FwPoolBase;
+PCHAR FwFreePool;
+
+extern ULONG ProcessorId;
+extern ULONG ProcessorRevision;
+extern ULONG ProcessorPageSize;
+extern ULONG NumberOfPhysicalAddressBits;
+extern ULONG MaximumAddressSpaceNumber;
+extern ULONG ProcessorCycleCounterPeriod;
+extern ULONG SystemRevisionId;
+extern PCHAR FirmwareVersion;
+
+
+VOID
+FwVendorInitialize(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the vendor private routines.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Initialize pointers and zero memory for the allocate pool routine.
+ //
+
+ FwPoolBase = (PCHAR)(FW_POOL_BASE | KSEG0_BASE);
+ FwFreePool = (PCHAR)(FW_POOL_BASE | KSEG0_BASE);
+ RtlZeroMemory(FwPoolBase, FW_POOL_SIZE);
+
+ //
+ // Initialize the vendor routine vector.
+ //
+
+ (PVEN_ALLOCATE_POOL_ROUTINE)SYSTEM_BLOCK->VendorVector[AllocatePoolRoutine] =
+ FwAllocatePool;
+
+ (PVEN_STALL_EXECUTION_ROUTINE)SYSTEM_BLOCK->VendorVector[StallExecutionRoutine] =
+ FwStallExecution;
+
+ (PVEN_PRINT_ROUTINE)SYSTEM_BLOCK->VendorVector[PrintRoutine] =
+ FwPrint;
+
+#ifndef FAILSAFE_BOOTER
+
+ (PVEN_RETURN_EXTENDED_SYSTEM_INFORMATION_ROUTINE)
+ SYSTEM_BLOCK->VendorVector[ReturnExtendedSystemInformationRoutine] =
+ FwReturnExtendedSystemInformation;
+
+#ifdef EISA_PLATFORM
+
+ (PVEN_VIDEO_DISPLAY_INITIALIZE_ROUTINE)
+ SYSTEM_BLOCK->VendorVector[VideoDisplayInitializeRoutine] =
+ DisplayBootInitialize;
+
+ (PVEN_EISA_READ_REGISTER_BUFFER_UCHAR_ROUTINE)
+ SYSTEM_BLOCK->VendorVector[EISAReadRegisterBufferUCHARRoutine] =
+ EISAReadRegisterBufferUCHAR;
+
+ (PVEN_EISA_WRITE_REGISTER_BUFFER_UCHAR_ROUTINE)
+ SYSTEM_BLOCK->VendorVector[EISAWriteRegisterBufferUCHARRoutine] =
+ EISAWriteRegisterBufferUCHAR;
+
+ (PVEN_EISA_READ_PORT_UCHAR_ROUTINE)
+ SYSTEM_BLOCK->VendorVector[EISAReadPortUCHARRoutine] =
+ EISAReadPortUCHAR;
+
+ (PVEN_EISA_READ_PORT_USHORT_ROUTINE)
+ SYSTEM_BLOCK->VendorVector[EISAReadPortUSHORTRoutine] =
+ EISAReadPortUSHORT;
+
+ (PVEN_EISA_READ_PORT_ULONG_ROUTINE)
+ SYSTEM_BLOCK->VendorVector[EISAReadPortULONGRoutine] =
+ EISAReadPortULONG;
+
+ (PVEN_EISA_WRITE_PORT_UCHAR_ROUTINE)
+ SYSTEM_BLOCK->VendorVector[EISAWritePortUCHARRoutine] =
+ EISAWritePortUCHAR;
+
+ (PVEN_EISA_WRITE_PORT_USHORT_ROUTINE)
+ SYSTEM_BLOCK->VendorVector[EISAWritePortUSHORTRoutine] =
+ EISAWritePortUSHORT;
+
+ (PVEN_EISA_WRITE_PORT_ULONG_ROUTINE)
+ SYSTEM_BLOCK->VendorVector[EISAWritePortULONGRoutine] =
+ EISAWritePortULONG;
+
+#endif // EISA_PLATFORM
+
+#endif
+
+ return;
+}
+
+
+PVOID
+FwAllocatePool(
+ IN ULONG NumberOfBytes
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates the requested number of bytes from the firmware
+ pool. If enough pool exists to satisfy the request, a pointer to the
+ next free cache-aligned block is returned, otherwise NULL is returned.
+ The pool is zeroed at initialization time, and no corresponding
+ "FwFreePool" routine exists.
+
+Arguments:
+
+ NumberOfBytes - Supplies the number of bytes to allocate.
+
+Return Value:
+
+ NULL - Not enough pool exists to satisfy the request.
+
+ NON-NULL - Returns a pointer to the allocated pool.
+
+--*/
+
+{
+ PVOID Pool;
+
+ //
+ // If there is not enough free pool for this request or the requested
+ // number of bytes is zero, return NULL, otherwise return a pointer to
+ // the free block and update the free pointer.
+ //
+
+ if (((FwFreePool + NumberOfBytes) > (FwPoolBase + FW_POOL_SIZE)) ||
+ (NumberOfBytes == 0)) {
+
+ Pool = NULL;
+
+ } else {
+
+ Pool = FwFreePool;
+
+ //
+ // Move pointer to the next cache aligned section of free pool.
+ //
+
+ FwFreePool += ((NumberOfBytes - 1) & ~(KeGetDcacheFillSize() - 1)) +
+ KeGetDcacheFillSize();
+ }
+ return Pool;
+}
+
+#ifndef FAILSAFE_BOOTER
+VOID
+FwReturnExtendedSystemInformation (
+ OUT PEXTENDED_SYSTEM_INFORMATION SystemInfo
+ )
+
+/*++
+
+Routine Description:
+
+ This returns detailed information about the Alpha AXP system and
+ processor.
+
+Arguments:
+
+ SystemInfo A structure with the system and processor info.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ SystemInfo->ProcessorId = ProcessorId;
+ SystemInfo->ProcessorRevision = ProcessorRevision;
+ SystemInfo->NumberOfPhysicalAddressBits = NumberOfPhysicalAddressBits;
+ SystemInfo->MaximumAddressSpaceNumber = MaximumAddressSpaceNumber;
+ SystemInfo->ProcessorCycleCounterPeriod = ProcessorCycleCounterPeriod;
+ SystemInfo->ProcessorPageSize = ProcessorPageSize;
+ SystemInfo->SystemRevision = SystemRevisionId;
+ strcpy (SystemInfo->FirmwareVersion, FirmwareVersion);
+
+
+ // Jensen systems do not have a serial number.
+ strcpy (SystemInfo->SystemSerialNumber, "0");
+
+ return;
+}
+#endif // ndef FAILSAFE_BOOTER
+
+#if !defined(FAILSAFE_BOOTER) && defined(EISA_PLATFORM)
+
+ULONG
+EISAReadRegisterBufferUCHAR (
+ IN ULONG BusNumber,
+ IN ULONG Offset,
+ OUT PVOID Buffer,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ This reads EISA memory space using byte reads.
+
+Arguments:
+
+ BusNumber EISA bus number, starting with 0.
+
+ Offset Byte offset from the beginning of EISA space for
+ this bus.
+
+ This must be based off the .IoStart value in the
+ EISA adapter's ConfigurationData, which is held in
+ the Component Data Structure node. Therefore, this
+ will already have the EISA QVA bits set up.
+
+ Buffer A pointer to the data area to receive the EISA data.
+
+ Length Number of bytes to read.
+
+
+Return Value:
+
+ This returns the number of bytes actually read. If this is not
+ equal to the Length argument, an error has occurred. Explicitly
+ detected errors are signalled by returning a value of 0.
+
+--*/
+
+{
+ //
+ // Check for illegal values for Jensen.
+ //
+
+ if (BusNumber != 0) {
+ return (0);
+ }
+
+ //
+ // Call HAL library function with QVA bit or'd in.
+ //
+
+ READ_REGISTER_BUFFER_UCHAR((PUCHAR)Offset, Buffer, Length);
+
+ return (Length);
+}
+
+#endif // ndef FAILSAFE_BOOTER
+
+#if !defined(FAILSAFE_BOOTER) && defined(EISA_PLATFORM)
+
+ULONG
+EISAWriteRegisterBufferUCHAR (
+ IN ULONG BusNumber,
+ IN ULONG Offset,
+ OUT PVOID Buffer,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ This writes EISA memory space using byte reads.
+
+Arguments:
+
+ BusNumber EISA bus number, starting with 0.
+
+ Offset Byte offset from the beginning of EISA space for
+ this bus.
+
+ This must be based off the .IoStart value in the
+ EISA adapter's ConfigurationData, which is held in
+ the Component Data Structure node. Therefore, this
+ will already have the EISA QVA bits set up.
+
+ Buffer A pointer to the data to be written to the EISA memory.
+
+ Length Number of bytes to write.
+
+
+Return Value:
+
+ This returns the number of bytes actually written. If this is not
+ equal to the Length argument, an error has occurred. Explicitly
+ detected errors are signalled by returning a value of 0.
+
+--*/
+
+{
+ //
+ // Check for illegal values for Jensen.
+ //
+
+ if (BusNumber != 0) {
+ return (0);
+ }
+
+ //
+ // Call HAL library function with QVA bit or'd in.
+ //
+
+ WRITE_REGISTER_BUFFER_UCHAR((PUCHAR)Offset, Buffer, Length);
+
+ return (Length);
+}
+
+#endif // ndef FAILSAFE_BOOTER
+
+#if !defined(FAILSAFE_BOOTER) && defined(EISA_PLATFORM)
+
+UCHAR
+EISAReadPortUCHAR (
+ IN ULONG BusNumber,
+ IN ULONG Offset
+ )
+/*++
+
+Routine Description:
+
+ This reads EISA I/O space using a byte read.
+
+ On Alpha, this is identical to reading EISA memory space.
+
+ On Alpha/Jensen we check for a read to 0C80--0C83, and manually
+ return the EISA System Board ID bytes.
+
+
+Arguments:
+
+ BusNumber EISA bus number, starting with 0.
+
+ Offset Byte offset from the beginning of EISA space for
+ this bus.
+
+ This must be based off the .IoStart value in the
+ EISA adapter's ConfigurationData, which is held in
+ the Component Data Structure node. Therefore, this
+ will already have the EISA QVA bits set up.
+
+Return Value:
+
+ This returns the byte read. On an error, 0 is returned.
+
+--*/
+
+{
+ //
+ // Check for illegal values for Jensen.
+ //
+
+ if (BusNumber != 0) {
+ return (0);
+ }
+
+ //
+ // Trap reads to System Board ID bytes and return Jensen ID bytes.
+ // which correspond to the EISA identifier "DEC2400".
+ //
+
+ switch (Offset & 0xffff) {
+
+ case 0x0c80:
+ return 0x10;
+
+ case 0x0c81:
+ return 0xa3;
+
+ case 0x0c82:
+ return 0x24;
+
+ case 0x0c83:
+ return 0x00;
+ }
+
+
+ //
+ // Call HAL library function with QVA bit or'd in.
+ //
+
+ return (READ_PORT_UCHAR((PUCHAR)Offset));
+}
+
+#endif // ndef FAILSAFE_BOOTER
+
+#if !defined(FAILSAFE_BOOTER) && defined(EISA_PLATFORM)
+
+USHORT
+EISAReadPortUSHORT (
+ IN ULONG BusNumber,
+ IN ULONG Offset
+ )
+/*++
+
+Routine Description:
+
+ This reads EISA I/O space using a word read.
+
+ On Alpha, this is identical to reading EISA memory space.
+
+ On Alpha/Jensen we check for a read to 0C80--0C83, and manually
+ return the EISA System Board ID bytes.
+
+
+Arguments:
+
+ BusNumber EISA bus number, starting with 0.
+
+ Offset Byte offset from the beginning of EISA space for
+ this bus.
+
+ This must be based off the .IoStart value in the
+ EISA adapter's ConfigurationData, which is held in
+ the Component Data Structure node. Therefore, this
+ will already have the EISA QVA bits set up.
+
+Return Value:
+
+ This returns the word read. On an error, 0 is returned.
+
+--*/
+
+{
+ //
+ // Check for illegal values for Jensen.
+ //
+
+ if ((BusNumber != 0) ||
+ ((Offset & 0x3) == 0x3)) {
+ return (0);
+ }
+
+ //
+ // Trap reads to System Board ID bytes and return Jensen ID bytes.
+ // which correspond to the EISA identifier "DEC2400".
+ //
+
+ switch (Offset & 0xffff) {
+
+ case 0x0c80:
+ return 0xa310;
+
+ case 0x0c82:
+ return 0x0024;
+
+ }
+
+
+ //
+ // Call HAL library function with QVA bit or'd in.
+ //
+
+ return (READ_PORT_USHORT((PUSHORT)Offset));
+}
+
+#endif // ndef FAILSAFE_BOOTER
+
+#if !defined(FAILSAFE_BOOTER) && defined(EISA_PLATFORM)
+
+ULONG
+EISAReadPortULONG (
+ IN ULONG BusNumber,
+ IN ULONG Offset
+ )
+/*++
+
+Routine Description:
+
+ This reads EISA I/O space using a longword read.
+
+ On Alpha, this is identical to reading EISA memory space.
+
+ On Alpha/Jensen we check for a read to 0C80--0C83, and manually
+ return the EISA System Board ID bytes.
+
+
+Arguments:
+
+ BusNumber EISA bus number, starting with 0.
+
+ Offset Byte offset from the beginning of EISA space for
+ this bus.
+
+ This must be based off the .IoStart value in the
+ EISA adapter's ConfigurationData, which is held in
+ the Component Data Structure node. Therefore, this
+ will already have the EISA QVA bits set up.
+
+Return Value:
+
+ This returns the longword read. On an error, 0 is returned.
+
+--*/
+
+{
+ //
+ // Check for illegal values for Jensen.
+ //
+
+ if ((BusNumber != 0) ||
+ ((Offset & 0x3) != 0)) {
+ return (0);
+ }
+
+ //
+ // Trap reads to System Board ID bytes and return Jensen ID bytes.
+ // which correspond to the EISA identifier "DEC2400".
+ //
+
+ if ((Offset & 0xffff) == 0x0c80) {
+ return 0x0024a310;
+ }
+
+
+ //
+ // Call HAL library function with QVA bit or'd in.
+ //
+
+ return (READ_PORT_ULONG((PULONG)Offset));
+}
+
+#endif // ndef FAILSAFE_BOOTER
+
+#if !defined(FAILSAFE_BOOTER) && defined(EISA_PLATFORM)
+
+VOID
+EISAWritePortUCHAR (
+ IN ULONG BusNumber,
+ IN ULONG Offset,
+ IN UCHAR Datum
+ )
+/*++
+
+Routine Description:
+
+ This writes EISA I/O space using a byte write. On Alpha, this is
+ identical to writing EISA memory space.
+
+Arguments:
+
+ BusNumber EISA bus number, starting with 0.
+
+ Offset Byte offset from the beginning of EISA space for
+ this bus.
+
+ This must be based off the .IoStart value in the
+ EISA adapter's ConfigurationData, which is held in
+ the Component Data Structure node. Therefore, this
+ will already have the EISA QVA bits set up.
+
+ Datum The byte to be written.
+
+Return Value:
+
+ None. Errors will cause either a no-op or a bugcheck.
+
+--*/
+
+{
+ //
+ // Check for illegal values for Jensen.
+ //
+
+ if (BusNumber != 0) {
+ return;
+ }
+
+ //
+ // Call HAL library function with QVA bit or'd in.
+ //
+
+ WRITE_PORT_UCHAR((PUCHAR)Offset, Datum);
+
+ return;
+}
+
+#endif // ndef FAILSAFE_BOOTER
+
+#if !defined(FAILSAFE_BOOTER) && defined(EISA_PLATFORM)
+
+VOID
+EISAWritePortUSHORT (
+ IN ULONG BusNumber,
+ IN ULONG Offset,
+ IN USHORT Datum
+ )
+/*++
+
+Routine Description:
+
+ This writes EISA I/O space using a word write. On Alpha, this is
+ identical to writing EISA memory space.
+
+Arguments:
+
+ BusNumber EISA bus number, starting with 0.
+
+ Offset Byte offset from the beginning of EISA space for
+ this bus.
+
+ This must be based off the .IoStart value in the
+ EISA adapter's ConfigurationData, which is held in
+ the Component Data Structure node. Therefore, this
+ will already have the EISA QVA bits set up.
+
+ Datum The short to be written.
+
+Return Value:
+
+ None. Errors will cause either a no-op or a bugcheck.
+
+--*/
+
+{
+ //
+ // Check for illegal values for Jensen.
+ //
+
+ if ((BusNumber != 0) ||
+ ((Offset & 0x3) == 0x3)) {
+ return;
+ }
+
+ //
+ // Call HAL library function with QVA bit or'd in.
+ //
+
+ WRITE_PORT_USHORT((PUSHORT)Offset, Datum);
+
+ return;
+}
+
+#endif // ndef FAILSAFE_BOOTER
+
+#if !defined(FAILSAFE_BOOTER) && defined(EISA_PLATFORM)
+
+VOID
+EISAWritePortULONG (
+ IN ULONG BusNumber,
+ IN ULONG Offset,
+ IN ULONG Datum
+ )
+/*++
+
+Routine Description:
+
+ This writes EISA I/O space using a longword write. On Alpha, this is
+ identical to writing EISA memory space.
+
+Arguments:
+
+ BusNumber EISA bus number, starting with 0.
+
+ Offset Byte offset from the beginning of EISA space for
+ this bus.
+
+ This must be based off the .IoStart value in the
+ EISA adapter's ConfigurationData, which is held in
+ the Component Data Structure node. Therefore, this
+ will already have the EISA QVA bits set up.
+
+ Datum The long to be written.
+
+Return Value:
+
+ None. Errors will cause either a no-op or a bugcheck.
+
+--*/
+
+{
+ //
+ // Check for illegal values for Jensen.
+ //
+
+ if ((BusNumber != 0) ||
+ ((Offset & 0x3) != 0)) {
+ return;
+ }
+
+ //
+ // Call HAL library function with QVA bit or'd in.
+ //
+
+ WRITE_PORT_ULONG((PULONG)Offset, Datum);
+
+ return;
+}
+
+#endif // ndef FAILSAFE_BOOTER
diff --git a/private/ntos/fw/alpha/kbdmouse.h b/private/ntos/fw/alpha/kbdmouse.h
new file mode 100644
index 000000000..3d6ba607e
--- /dev/null
+++ b/private/ntos/fw/alpha/kbdmouse.h
@@ -0,0 +1,164 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ Kbdmouse.h
+
+Abstract:
+
+ This module contains definitions for the keyboard controller
+ in typical industry-standard chips, like those in the jazz
+ and Alpha/Jensen systems.
+
+ It supports Mouse and Keyboard.
+
+Author:
+
+ Lluis Abello (lluis) 11-Jul-1990
+
+Environment:
+
+
+Revision History:
+
+ 19-August-1992 John DeRosa [DEC]
+
+ Alpha modifications.
+
+--*/
+
+#ifndef _KBDMOUSE_
+#define _KBDMOUSE_
+
+//
+// Keyboard Controller Commands
+//
+
+#define KBD_CTR_WRITE_COMMAND 0x60
+#define KBD_CTR_READ_COMMAND 0x20
+#define KBD_CTR_TEST_PASSWORD 0xA4
+#define KBD_CTR_LOAD_PASSWORD 0xA5
+#define KBD_CTR_ENABLE_PASSWORD 0xA6
+#define KBD_CTR_DISABLE_AUX 0xA7
+#define KBD_CTR_ENABLE_AUX 0xA8
+#define KBD_CTR_AUXLINES_TEST 0xA9
+#define KBD_CTR_SELFTEST 0xAA
+#define KBD_CTR_KBDLINES_TEST 0xAB
+#define KBD_CTR_ENABLE_KBD 0xAE
+#define KBD_CTR_WRITE_AUX 0xD4
+
+//
+// Keyboard Controller Data
+//
+
+#define Kbd_Ctr_Selftest_Passed 0x55
+#define Kbd_Ctr_Password_Installed 0xFA
+#define Kbd_Ctr_Password_Not_Installed 0xF1
+
+//
+// Controller Command Byte bit definitions.
+//
+
+#define KbdCommandByteDisableAux (1 << 5)
+#define KbdCommandByteDisableKbd (1 << 4)
+#define KbdCommandEnableAuxInt (1 << 1)
+#define KbdCommandEnableKbdInt (1 << 0)
+
+//
+// Keyboard Controller Status byte masks
+//
+
+#define KBD_OBF_MASK 0x1 // Output buffer full
+#define KBD_IBF_MASK 0x2 // Input buffer full
+#define KBD_FROM_AUX_MASK 0x20 // Byte from Aux Port.
+
+//
+// Interface Test Results
+//
+
+#define INTERFACE_NO_ERROR 0x00
+#define CLOCK_STUCK_LOW 0x01
+#define CLOCK_STUCK_HIGH 0x02
+#define DATA_STUCK_LOW 0x03
+#define DATA_STUCK_HIGH 0x04
+
+//
+// Timeout
+//
+
+#define KBD_TIMEOUT 0xFFFFF
+#define KBD_INT_TIMEOUT 0xFFFF
+
+
+//
+// The NT firmware expects to find a 101-key keyboard. It puts it into
+// XT mode (scan code 01).
+//
+//
+
+
+//
+// Keyboard Commands
+//
+
+#define KbdEcho 0xee // request keyboard to return echo response "EE"
+#define KbdSelScanCode 0xf0 // Scan codes 1,2,3 or 0 = rquest current.
+#define KbdReadID 0xf2 // Request for two byte response
+#define KbdSetRate 0xf3 // Set tellematic Rate
+#define KbdEnable 0xF4 // Clears Buffer and Starts Scanning.
+#define KbdDisable 0xF5 // reset to power up
+
+#define KbdSetDefault 0xf6 //
+#define KbdSetAllTlmtic 0xf7 // Set all keys telematic
+#define KbdSetAllMkBr 0xf8 // Set all keys Make /Break
+#define KbdSetAllMake 0xf9 // Set all keys Make only
+#define KbdSetKeyTlmtic 0xfb // Set individual key telemativ
+#define KbdSetKeyMkBr 0xfc // set individual key make/break
+#define KbdSetKeyMk 0xfd // set individual key make only
+#define KbdResend 0xfe // request to resend last transfer
+#define KbdReset 0xff // request to start a program reset
+#define KbdAck 0xfa // keyboard ack after reset
+#define KbdBat 0xAA // Keyboard Bat completion Response
+
+//
+// Define scan codes.
+//
+
+#define KEY_KEYPAD_MINUS 0x4a
+#define KEY_KEYPAD_PLUS 0x4e
+#define KEY_LEFT_SHIFT 0x2A
+#define KEY_RIGHT_SHIFT 0X36
+#define KEY_CAPS_LOCK 0X3A
+#define KEY_CONTROL 0X1D
+#define KEY_ALT 0X38
+#define KEY_UP_ARROW 0X48
+#define KEY_DOWN_ARROW 0X50
+#define KEY_LEFT_ARROW 0X4B
+#define KEY_RIGHT_ARROW 0X4D
+#define KEY_HOME 0X47
+#define KEY_END 0X4F
+#define KEY_INSERT 0X52
+#define KEY_DELETE 0X53
+#define KEY_SYS_REQUEST 0X54
+#define KEY_PRINT_SCREEN 0x37
+#define KEY_ESC 0x01
+#define KEY_PAGE_UP 0x49
+#define KEY_PAGE_DOWN 0x51
+#define KEY_F1 0x3B
+#define KEY_F2 0x3C
+#define KEY_F3 0x3D
+#define KEY_F4 0x3E
+#define KEY_F5 0x3F
+#define KEY_F6 0x40
+#define KEY_F7 0x41
+#define KEY_F8 0x42
+#define KEY_F9 0x43
+#define KEY_F10 0x44
+#define KEY_F11 0x57
+#define KEY_F12 0x58
+
+
+#endif //_KBDMOUSE_
diff --git a/private/ntos/fw/alpha/kbdtest.c b/private/ntos/fw/alpha/kbdtest.c
new file mode 100644
index 000000000..f1725227c
--- /dev/null
+++ b/private/ntos/fw/alpha/kbdtest.c
@@ -0,0 +1,414 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ Kbdtest.c
+
+Abstract:
+
+ This module implements the Keyboard and mouse test for the self-test.
+
+Author:
+
+ Lluis Abello (lluis) 10-Feb-1991
+
+Environment:
+
+ Rom self-test.
+
+Revision History:
+
+ 10-July-1992 John DeRosa [DEC]
+
+ Added Alpha/Jensen modifications.
+
+--*/
+#include <ntos.h>
+#include "iodevice.h"
+#include "kbdmouse.h"
+
+#ifdef JENSEN
+#include "jnsnprom.h"
+#include "jnsnrtc.h"
+#else
+#include "mrgnrtc.h" // morgan
+#endif
+
+volatile ULONG TimerTicks;
+
+//
+// If the user accidentally types on the keyboard or moves the mouse
+// during the power-up tests, there will be a failure. So, this code
+// retries an initialization of the keyboard controller and keyboard
+// this many times before giving up.
+//
+
+#define MAXIMUM_KEYBOARD_MOUSE_RETRY_COUNT 20
+
+//
+// function prototypes
+//
+
+VOID
+FwpWriteIOChip(
+ ULONG ComboInternalAddress,
+ UCHAR ComboRegisterAddress
+ );
+
+VOID
+ClearKbdFifo(
+ )
+/*++
+
+Routine Description:
+
+ This routine empties the Keyboard controller Fifo.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ UCHAR Trash, Stat;
+ volatile Timeout;
+
+ //
+ // wait until the previous command is processed.
+ //
+
+ while ((READ_PORT_UCHAR((PUCHAR)&KEYBOARD_READ->Status) & KBD_IBF_MASK) != 0) {
+ }
+ while ((READ_PORT_UCHAR((PUCHAR)&KEYBOARD_READ->Status) & KBD_OBF_MASK) != 0) {
+ Trash= READ_PORT_UCHAR((PUCHAR)&KEYBOARD_READ->Data);
+ for (Timeout=0;Timeout<10000;Timeout++) {
+ }
+ }
+}
+
+BOOLEAN
+GetKbdData(
+ PUCHAR C,
+ ULONG msec
+ )
+/*++
+
+Routine Description:
+
+ This routine polls the Status Register until Data is available or timeout,
+ then it reads and returns the Data.
+
+Arguments:
+
+ C - pointer to a byte where to write the read value
+ msec - time-out time in milliseconds
+
+Return Value:
+
+ TRUE if timeout, FALSE if OK;
+
+--*/
+{
+ //
+ // HACKHACK: This should be made smarter. For now it assumes
+ // 90,000,000 instruction per second and 12 instructions per iteration.
+ //
+
+ TimerTicks = msec * 1000 * 90 / 12;
+
+ while (TimerTicks--) {
+ if (READ_PORT_UCHAR((PUCHAR)&KEYBOARD_READ->Status) & KBD_OBF_MASK) {
+ *C = READ_PORT_UCHAR((PUCHAR)&KEYBOARD_READ->Data);
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+BOOLEAN
+SendKbdData(
+ IN UCHAR Data
+ )
+/*++
+
+Routine Description:
+
+ This routine polls the Status Register until the controller is ready to
+ accept a data or timeout, then it send the Data.
+
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ TRUE if timeout, FALSE if OK;
+
+--*/
+{
+ ULONG i;
+
+ for (i=0; i <KBD_TIMEOUT; i++) {
+ if ((READ_PORT_UCHAR((PUCHAR)&KEYBOARD_READ->Status) & KBD_IBF_MASK) == 0) {
+ WRITE_PORT_UCHAR((PUCHAR)&KEYBOARD_WRITE->Data,Data);
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+BOOLEAN
+SendKbdCommand(
+ IN UCHAR Command
+ )
+/*++
+
+Routine Description:
+
+ This routine polls the Status Register until the controller is ready to
+ accept a command or timeout, then it send the Command.
+
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ TRUE if timeout, FALSE if OK;
+
+--*/
+{
+ ULONG i;
+
+ for (i=0; i <KBD_TIMEOUT; i++) {
+ if ((READ_PORT_UCHAR((PUCHAR)&KEYBOARD_READ->Status) & KBD_IBF_MASK) == 0) {
+ WRITE_PORT_UCHAR((PUCHAR)&KEYBOARD_WRITE->Command,Command);
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+BOOLEAN
+InitKeyboard(
+ )
+/*++
+
+Routine Description:
+
+ This routine enables and initializes the keyboard. It assumes a
+ 101-key keyboard. It leaves the keyboard in XT mode (scan code = 01).
+
+ To account for the user accidentally typing on the keyboard, this
+ routine repeats the test a few times before giving up.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ FALSE if passed,
+
+ TRUE if bad ACK or BAT received, or if no response is received from
+ the keyboard.
+
+--*/
+{
+ UCHAR Result;
+ ULONG i;
+ ULONG Index;
+ BOOLEAN TestPassed;
+
+ TestPassed = FALSE;
+
+ for (Index = 0; Index < MAXIMUM_KEYBOARD_MOUSE_RETRY_COUNT; Index++) {
+
+ //
+ // Send Reset to Keyboard.
+ //
+
+ ClearKbdFifo();
+ for (;;) {
+ if (SendKbdData(KbdReset)) {
+ goto LoopAgain;
+ }
+ if (GetKbdData(&Result,1000)) {
+ goto LoopAgain;
+ }
+ if (Result == KbdResend) {
+ if (GetKbdData(&Result,1000)) {
+ goto LoopAgain;
+ }
+ continue;
+ }
+ if (Result != KbdAck) {
+ goto LoopAgain;
+ }
+ if (GetKbdData(&Result,7000)) {
+ goto LoopAgain;
+ }
+ if (Result != KbdBat) {
+ goto LoopAgain;
+ }
+ break;
+ }
+
+ //
+ // Enable Kbd and Select keyboard Scan code.
+ //
+
+ if (SendKbdCommand(KBD_CTR_ENABLE_KBD)) {
+ continue;
+ }
+ if (SendKbdData(KbdSelScanCode)) {
+ continue;
+ }
+ if (GetKbdData(&Result,1000)) {
+ continue;
+ }
+ if (SendKbdData(1)) { // select Scan code 1
+ continue;
+ }
+ if (GetKbdData(&Result,1000)) {
+ continue;
+ }
+
+ TestPassed = TRUE;
+ break;
+
+ //
+ // Here when an inner loop init fails and we want to do the outer
+ // loop again.
+ //
+
+ LoopAgain:
+
+ continue;
+ }
+
+ if (TestPassed) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
+
+
+ULONG
+InitKeyboardController(
+ )
+/*++
+
+Routine Description:
+
+ This routine Initializes the Keyboard controller. To account for
+ the user accidentally moving the mouse or typing on the keyboard, this
+ routine repeats the test a few times before giving up.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ FALSE if passed,
+ TRUE if bad response received from keyboard controller,
+
+--*/
+{
+ UCHAR Result;
+ ULONG Index;
+ BOOLEAN TestPassed;
+
+ TestPassed = FALSE;
+
+ for (Index = 0; Index < MAXIMUM_KEYBOARD_MOUSE_RETRY_COUNT; Index++) {
+
+ //
+ // Clear both fifos.
+ //
+
+ ClearKbdFifo();
+
+ //
+ // Init Control Register 1 with the PS/2/AT bit clear.
+ // This puts the keyboard into PS/2 mode.
+ //
+
+ FwpWriteIOChip (RTC_APORT, RTC_REGNUMBER_RTC_CR1);
+ Result = FwpReadIOChip(RTC_DPORT) & ~0x2;
+ FwpWriteIOChip (RTC_APORT, RTC_REGNUMBER_RTC_CR1);
+ FwpWriteIOChip (RTC_DPORT, Result);
+
+
+ //
+ // Send Selftest Command. This has to be done before anything else.
+ //
+
+ if (SendKbdCommand(KBD_CTR_SELFTEST)) {
+ continue;
+ }
+ if (GetKbdData(&Result,1000)) {
+ continue;
+ }
+ if (Result != Kbd_Ctr_Selftest_Passed) {
+ continue;
+ }
+
+ //
+ // Now the Keyboard and Mouse are disabled.
+ //
+
+ //
+ // Test Keyboard lines.
+ //
+
+ if (SendKbdCommand(KBD_CTR_KBDLINES_TEST)) {
+ continue;
+ }
+ if (GetKbdData(&Result,1000)) {
+ continue;
+ }
+ if (Result != INTERFACE_NO_ERROR) {
+ continue;
+ }
+
+ //
+ // Test Aux lines.
+ //
+
+ if (SendKbdCommand(KBD_CTR_AUXLINES_TEST)) {
+ continue;
+ }
+ if (GetKbdData(&Result,1000)) {
+ continue;
+ }
+#ifndef ALPHA
+ // This test is disabled for Alpha/Jensen. It fails for some reason,
+ // but the VMS/OSF console front-end has more comprehensive
+ // tests than this routine anyway.
+ if (Result != INTERFACE_NO_ERROR) {
+ continue;
+ }
+#endif
+ TestPassed = TRUE;
+ break;
+
+ }
+
+ if (TestPassed) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
diff --git a/private/ntos/fw/alpha/kdstubs.c b/private/ntos/fw/alpha/kdstubs.c
new file mode 100644
index 000000000..bd4b0f61b
--- /dev/null
+++ b/private/ntos/fw/alpha/kdstubs.c
@@ -0,0 +1,201 @@
+#ifdef ALPHA_FW_KDHOOKS
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ kdstubs.c
+
+Abstract:
+
+ This module implements stub routines for the kernel debugger.
+
+Authors:
+
+ John DeRosa and Joe Notarangelo
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "ntos.h"
+#include "fwp.h"
+
+extern PKPCR KiPcrBaseAddress;
+
+//
+// This is a global used for spin-locking in the kernel debugger
+// stub.
+//
+
+KSPIN_LOCK KdpDebuggerLock;
+
+VOID
+HalDisplayString (
+ IN PCHAR String
+ )
+{
+ FwPrint(String);
+}
+
+//
+// For a function in hal\alpha\jxport.c
+//
+
+PCONFIGURATION_COMPONENT_DATA
+KeFindConfigurationEntry (
+ IN PCONFIGURATION_COMPONENT_DATA Child,
+ IN CONFIGURATION_CLASS Class,
+ IN CONFIGURATION_TYPE Type,
+ IN PULONG Key OPTIONAL
+ )
+
+{
+ return NULL;
+}
+
+VOID
+KiAcquireSpinLock (
+ IN PKSPIN_LOCK SpinLock,
+ OUT PKIRQL OldIrql
+ )
+{
+ return;
+}
+
+
+VOID
+KiReleaseSpinLock (
+ IN PKSPIN_LOCK SpinLock
+ )
+{
+ return;
+}
+
+BOOLEAN
+KiTryToAcquireSpinLock (
+ IN PKSPIN_LOCK SpinLock,
+ OUT PKIRQL OldIrql
+ )
+{
+ return TRUE;
+}
+
+BOOLEAN
+KiDisableInterrupts (
+ VOID
+ )
+{
+ return FALSE;
+}
+
+VOID
+KiRestoreInterrupts (
+ BOOLEAN InterruptFlag
+ )
+{
+ return;
+}
+
+VOID
+KeSweepIcache (
+ IN BOOLEAN AllProcessors
+ )
+{
+ AlphaInstIMB();
+}
+
+PKPCR
+KeGetPcr (
+ VOID
+ )
+{
+ return (KiPcrBaseAddress);
+}
+
+VOID
+KeInitializeInterrupt (
+ IN PKINTERRUPT Interrupt,
+ IN PKSERVICE_ROUTINE ServiceRoutine,
+ IN PVOID ServiceContext,
+ IN PKSPIN_LOCK SpinLock OPTIONAL,
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KIRQL SynchronizeIrql,
+ IN KINTERRUPT_MODE InterruptMode,
+ IN BOOLEAN ShareVector,
+ IN CCHAR ProcessorNumber,
+ IN BOOLEAN FloatingSave
+ )
+{
+ return;
+}
+
+BOOLEAN
+KeConnectInterrupt (
+ IN PKINTERRUPT Interrupt
+ )
+{
+ return TRUE;
+}
+
+VOID
+KeRaiseIrql (
+ KIRQL NewIrql,
+ PKIRQL OldIrql
+ )
+{
+ return;
+}
+
+VOID
+KeLowerIrql (
+ KIRQL NewIrql
+ )
+{
+ return;
+}
+
+VOID
+KeProfileInterrupt (
+ IN PKTRAP_FRAME TrapFrame
+ )
+{
+ return;
+}
+
+VOID
+KeUpdateSystemTime (
+ IN PKTRAP_FRAME TrapFrame
+ )
+{
+ return;
+}
+
+VOID
+KeStallExecutionProcessor (
+ IN ULONG Microseconds
+ )
+{
+ FwStallExecution(Microseconds);
+ return;
+}
+
+VOID
+HalReturnToFirmware(
+ IN FIRMWARE_REENTRY Routine
+ )
+
+{
+ AlphaInstHalt();
+}
+
+
+#endif
diff --git a/private/ntos/fw/alpha/monitor.c b/private/ntos/fw/alpha/monitor.c
new file mode 100644
index 000000000..76d9918c4
--- /dev/null
+++ b/private/ntos/fw/alpha/monitor.c
@@ -0,0 +1,1785 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ monitor.c
+
+Abstract:
+
+ This file contains the monitor for the firmware.
+
+Author:
+
+ Lluis Abello (lluis) 09-Sep-91
+
+Revision History:
+
+ 26-May-1992 John DeRosa [DEC]
+
+ Added Alpha/Jensen modifications.
+
+--*/
+
+#include "fwp.h"
+#include "iodevice.h"
+#include "monitor.h"
+#include "sys\types.h"
+#include "string.h"
+#include "fwstring.h"
+
+#define BYTE 1
+#define HALF 2
+#define MON_LONGWORD 4
+#define MON_QUAD 8
+
+
+VOID
+FillVideoMemory(
+ IN ULONG,
+ IN ULONG,
+ IN ULONG
+ );
+
+
+//
+// declare static variables.
+//
+ULONG Argc;
+ULONG CurrentArg;
+
+COMMAND_NAME_ID CurrentCommand;
+
+ULONG DataSize;
+ULONG DataSizeMask;
+ULONG DataSizeShift;
+
+ULONG DefaultAddress;
+
+// ****** temp ******
+// strtoul sets errno in case of overflow and is not declared anywhere else.
+//
+ULONG errno;
+
+PCHAR RegisterNameTable[(REGISTER_NAME_ID)invalidregister] = {
+ "???", // reserved for exception type
+ "ex1", // exception parameter 1
+ "ex2", // exception parameter 2
+ "ex3", // exception parameter 3
+ "ex4", // exception parameter 4
+ "ex5", // exception parameter 5
+ "psr", // exception psr
+ "mmc", // exception mm csr
+ "eva", // exception va
+ "pc", // exception pc
+ "v0", // general register 0
+ "t0", // general register 1
+ "t1", // general register 2
+ "t2", // general register 3
+ "t3", // general register 4
+ "t4", // general register 5
+ "t5", // general register 6
+ "t6", // general register 7
+ "t7", // general register 8
+ "s0", // general register 9
+ "s1", // general register 10
+ "s2", // general register 11
+ "s3", // general register 12
+ "s4", // general register 13
+ "s5", // general register 14
+ "fp", // general register 15
+ "a0", // general register 16
+ "a1", // general register 17
+ "a2", // general register 18
+ "a3", // general register 19
+ "a4", // general register 20
+ "a5", // general register 21
+ "t8", // general register 22
+ "t9", // general register 23
+ "t10", // general register 24
+ "t11", // general register 25
+ "ra", // general register 26
+ "t12", // general register 27
+ "at", // general register 28
+ "gp", // general register 29
+ "sp", // general register 30
+ "zero", // general register 31
+ "f0", // fp register 0
+ "f1", // fp register 1
+ "f2", // fp register 2
+ "f3", // fp register 3
+ "f4", // fp register 4
+ "f5", // fp register 5
+ "f6", // fp register 6
+ "f7", // fp register 7
+ "f8", // fp register 8
+ "f9", // fp register 9
+ "f10", // fp register 10
+ "f11", // fp register 11
+ "f12", // fp register 12
+ "f13", // fp register 13
+ "f14", // fp register 14
+ "f15", // fp register 15
+ "f16", // fp register 16
+ "f17", // fp register 17
+ "f18", // fp register 18
+ "f19", // fp register 19
+ "f20", // fp register 20
+ "f21", // fp register 21
+ "f22", // fp register 22
+ "f23", // fp register 23
+ "f24", // fp register 24
+ "f25", // fp register 25
+ "f26", // fp register 26
+ "f27", // fp register 27
+ "f28", // fp register 28
+ "f29", // fp register 29
+ "f30", // fp register 30
+ "f31" // fp register 31
+ };
+
+
+// This is indexed by the low bits of the ExceptionType.
+PCHAR ExceptionNameTable[14] = {
+ "** Machine Check", // exception code 0
+ "** Arithmetic", // exception code 1
+ "** Interrupt", // exception code 2
+ "** D-Stream Memory Fault", // exception code 3
+ "** I-Stream TB Miss", // exception code 4
+ "** I-Stream ACV", // exception code 5
+ "** Native D-Stream TB Miss", // exception code 6
+ "** PALcode D-Stream TB Miss", // exception code 7
+ "** Unaligned Data", // exception code 8
+ "** Opcode Reserved To DEC", // exception code 9
+ "** Floating Point Enable", // exception code a
+ "** Halt", // exception code b
+ "** Breakpoint", // exception code c
+ "** Divide by Zero" // exception code d
+ };
+
+
+
+//
+// I/O Write commands, and Available Devices, are disabled in the product.
+//
+
+#if 0
+
+PCHAR CommandNameTable[(COMMAND_NAME_ID)invalidcommand] = {
+ "d",
+ "db",
+ "dw",
+ "dl",
+ "dq",
+ "e",
+ "eb",
+ "ew",
+ "el",
+ "eq",
+ "h",
+ "?",
+ "de",
+ "deb",
+ "dew",
+ "del",
+ "deq",
+ "ex",
+ "exb",
+ "exw",
+ "exl",
+ "exq",
+ "ior",
+ "iorb",
+ "iorw",
+ "iorl",
+ "iow",
+ "iowb",
+ "ioww",
+ "iowl",
+ "r",
+ "ir",
+ "fr",
+ "z",
+ "f",
+ "a",
+ "q"
+ };
+
+#else
+
+PCHAR CommandNameTable[(COMMAND_NAME_ID)invalidcommand] = {
+ "d",
+ "db",
+ "dw",
+ "dl",
+ "dq",
+ "e",
+ "eb",
+ "ew",
+ "el",
+ "eq",
+ "h",
+ "?",
+ "de",
+ "deb",
+ "dew",
+ "del",
+ "deq",
+ "ex",
+ "exb",
+ "exw",
+ "exl",
+ "exq",
+ "ior",
+ "iorb",
+ "iorw",
+ "iorl",
+ "r",
+ "ir",
+ "fr",
+ "z",
+ "f",
+ "q"
+ };
+
+#endif
+
+
+// Alpha/Jensen passes register table in as pointer to structure.
+//extern ULONG RegisterTable[(REGISTER_NAME_ID)invalidregister];
+
+extern LONG FwColumn;
+extern LONG FwRow;
+
+
+REGISTER_NAME_ID
+GetRegister(
+ IN PCHAR RegName
+ )
+
+/*++
+
+Routine Description:
+
+ This routine returns the index in the exception frame for the
+ given register. Or invalid if the given register name doesn't
+ match any register.
+
+Arguments:
+
+ RegName - Null terminated string that contains the name of the register.
+
+Return Value:
+
+ Index for the requested register.
+
+--*/
+
+{
+ REGISTER_NAME_ID RegId;
+
+ for (RegId = 0; RegId < invalidregister; RegId++) {
+ if (strcmp(RegisterNameTable[RegId],RegName) == 0) {
+ break;
+ }
+ }
+ return RegId;
+}
+
+
+BOOLEAN
+GetAddress(
+ IN PUCHAR String,
+ IN PFW_EXCEPTION_FRAME Frame,
+ OUT PULONG Address
+ )
+
+/*++
+
+Routine Description:
+
+ This routine converts an ascii string to an address. The string
+ is the form:
+ [@reg | value]
+
+Arguments:
+
+ String - Null terminated string that contains the address to convert.
+ Frame - Address of the exception frame that was passed to Monitor.
+ Address - Supplies a pointer to where the converted address is stored
+
+Return Value:
+
+ Returns TRUE if the string can be converted.
+ FALSE otherwise.
+
+--*/
+
+{
+ PUCHAR Terminator;
+ UCHAR Delimiter;
+ REGISTER_NAME_ID RegId;
+
+ if (*String == '@') {
+ String++; // skip @
+ if ((RegId = GetRegister(String)) == invalidregister) {
+ FwPrint(String);
+ FwPrint(MON_INVALID_REGISTER_MSG);
+ return FALSE;
+ } else {
+ //
+ // This is a hack to treat the structure as an array. It
+ // should have been an array to begin with. RegId is an
+ // index into the "array".
+ //
+ *Address = ((PULONGLONG)Frame)[RegId];
+ }
+ } else {
+ *Address=strtoul(String,&Terminator,16);
+ if (*Terminator != '\0') {
+ //
+ // Not the whole string was converted.
+ //
+ FwPrint(Terminator);
+ FwPrint(MON_NOT_VALID_ADDRESS_MSG);
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+BOOLEAN
+GetAddressRange(
+ IN PCHAR Argv[],
+ IN PFW_EXCEPTION_FRAME Frame,
+ OUT PULONG StartAddress,
+ OUT PULONG EndAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This routine converts an ascii string to a range, returning the starting
+ and end address.
+
+ The syntax for an address range is one of the following
+
+ startaddress endaddres
+ startaddress l numberofelements
+
+Arguments:
+
+ Argv - array of zero terminated argument strings.
+ Frame - Address of the exception frame that was passed to Monitor.
+ StartAddress - Supplies a pointer to where the Start address is stored
+ EndAddress - Supplies a pointer to where the End address is stored
+
+Return Value:
+
+ Returns TRUE if Argv specifies a valid address range.
+ FALSE otherwise.
+
+--*/
+
+{
+ PCHAR Tmp;
+ CHAR Delimiter;
+
+ if (CurrentArg == Argc) {
+ return;
+ }
+ if (GetAddress(Argv[CurrentArg],Frame,StartAddress) == FALSE) {
+ return FALSE;
+ }
+ CurrentArg++;
+ if (CurrentArg == Argc) {
+ *EndAddress = *StartAddress+128;
+ return TRUE;
+ }
+ if (strcmp(Argv[CurrentArg],"l") == 0 ) {
+ //
+ // this is a range of the form "startaddress l count"
+ //
+ CurrentArg++;
+ if (CurrentArg == Argc) {
+ FwPrint(MON_INVALID_ARGUMENT_COUNT_MSG);
+ return FALSE;
+ }
+ if (GetAddress(Argv[CurrentArg],Frame,EndAddress) == FALSE) {
+ return FALSE;
+ }
+ CurrentArg++;
+ *EndAddress = (*EndAddress<<DataSizeShift) + *StartAddress;
+ } else {
+ if (GetAddress(Argv[CurrentArg],Frame,EndAddress) == FALSE) {
+ //
+ // the argument didn't convert the range is Start+128
+ //
+ *EndAddress = *StartAddress+128;
+ } else {
+ CurrentArg++;
+ }
+ }
+ //
+ // Check that the range is correct End > Start
+ //
+ if (*EndAddress <= *StartAddress) {
+ FwPrint(MON_INVALID_ADDRESS_RANGE_MSG);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+COMMAND_NAME_ID
+GetCommand(
+ IN PCHAR CommandName
+ )
+
+/*++
+
+Routine Description:
+
+ This routine tries to match the supplied string
+ with one of the recognized commands.
+
+Arguments:
+
+ CommandName - Supplies a string to be matched with one of the monitor commands.
+
+Return Value:
+
+ Returns a value that identifies the command.
+
+--*/
+{
+ COMMAND_NAME_ID Index;
+ for (Index=0;Index<invalidcommand;Index++) {
+ if (strcmp(CommandNameTable[Index],CommandName) == 0) {
+ break;
+ }
+ }
+ return Index;
+}
+
+BOOLEAN
+RegisterCommand(
+ IN PCHAR Argv[],
+ IN PFW_EXCEPTION_FRAME Frame
+ )
+
+/*++
+
+Routine Description:
+
+ This routine will implement the Register, IntegerRegisterDump,
+ and FloatingRegisterDump commands given the arguments in the
+ argc,Argv form.
+
+Arguments:
+
+ Argv - array of zero terminated argument strings.
+
+ Frame - the saved register & exception state.
+
+
+Return Value:
+
+ Returns TRUE if the command is valid, FALSE otherwise.
+
+--*/
+{
+ REGISTER_NAME_ID RegId;
+ CHAR Message[64];
+
+ if (
+ ((strcmp(Argv[0], "ir") == 0) || (strcmp(Argv[0], "fr") == 0))
+ &&
+ (Argc != 1)
+ ) {
+ // invalid ir or fr command.
+ FwPrint(MON_INVALID_ARGUMENT_COUNT_MSG);
+ return FALSE;
+ }
+
+
+ if (
+ (strcmp(Argv[0], "r") == 0)
+ &&
+ (Argc != 2)
+ ) {
+ // invalid r command.
+ FwPrint(MON_INVALID_ARGUMENT_COUNT_MSG);
+ return FALSE;
+ }
+
+
+
+ if (strcmp(Argv[0], "ir") == 0) {
+
+ //
+ // ir command, and we know the argument count is 1.
+ // Dump the integer registers.
+ //
+
+ for (RegId=1;RegId<42;RegId++) {
+
+ sprintf(Message," %4s=%016Lx",RegisterNameTable[RegId],
+ ((PULONGLONG)Frame)[RegId]);
+
+ FwPrint(Message);
+
+ if ((RegId%3) == 0) {
+ FwPrint(FW_CRLF_MSG);
+ }
+ }
+
+ FwPrint(FW_CRLF_MSG);
+ return TRUE;
+ }
+
+
+
+ if (strcmp(Argv[0], "fr") == 0) {
+
+ //
+ // fr command, and we know the argument count is 1.
+ // Dump the floating point registers.
+ //
+
+ for (RegId=42;RegId<74;RegId++) {
+
+ sprintf(Message," %3s=%016Lx",RegisterNameTable[RegId],
+ ((PULONGLONG)Frame)[RegId]);
+
+ FwPrint(Message);
+
+ if ((RegId%3) == 2) {
+ FwPrint(FW_CRLF_MSG);
+ }
+ }
+
+ FwPrint(FW_CRLF_MSG);
+ return TRUE;
+ }
+
+
+
+
+ if (strcmp(Argv[0], "r") == 0) {
+
+ //
+ // r command, and we know the argument count is 2.
+ // Dump the specified register.
+ //
+
+ if ((RegId = GetRegister(Argv[1])) == invalidregister) {
+ FwPrint(Argv[1]);
+ FwPrint(MON_INVALID_REGISTER_MSG);
+ return FALSE;
+ } else {
+ sprintf(Message,"%s = %016Lx\r\n",RegisterNameTable[RegId],
+ ((PULONGLONG)Frame)[RegId]);
+ FwPrint(Message);
+ return TRUE;
+ }
+ }
+
+}
+
+VOID
+ExamineValue(
+ IN ULONG Address,
+ OUT PVOID Value
+ )
+/*++
+
+Routine Description:
+
+ This reads a value from the supplied address and displays it.
+
+Arguments:
+
+ Address - Supplies the address where the value is to be read from.
+ Value - Pointer to where the value read is stored if DataSize = BYTE.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ CHAR Message[32];
+
+ switch(DataSize) {
+ case BYTE:
+ *(PUCHAR)Value = *(PUCHAR)Address;
+ sprintf(Message,"%02x ",*(PUCHAR)Value);
+ break;
+ case HALF:
+ sprintf(Message,"%04x ",*(PUSHORT)Address);
+ break;
+ case MON_LONGWORD:
+ sprintf(Message,"%08lx ",*(PULONG)Address);
+ break;
+ case MON_QUAD:
+ sprintf(Message,"%016Lx ", *(PULONGLONG)Address);
+ break;
+ }
+
+ FwPrint(Message);
+}
+
+
+BOOLEAN
+DumpCommand(
+ IN PCHAR Argv[],
+ IN PFW_EXCEPTION_FRAME Frame
+ )
+/*++
+
+Routine Description:
+
+ This routine will implement the DUMP command given the
+ arguments in the argc,Argv form.
+
+Arguments:
+
+ Argv - array of zero terminated argument strings.
+ Frame - the saved register & exception state.
+
+Return Value:
+
+ Returns TRUE if the command is valid, FALSE otherwise.
+
+--*/
+
+{
+ ULONG Start,End;
+ ULONG i,LineLength;
+ ULONG DataLine[16];
+ UCHAR Message[32];
+ //
+ // Set the right range of addresses. If none specified use last
+ // set of addresses+128.
+ //
+ if (Argc == 1) {
+ Start = DefaultAddress;
+ End = Start + 128;
+ } else {
+ if (GetAddressRange(Argv,Frame,&Start,&End) == FALSE) {
+ return FALSE;
+ }
+ //
+ // if after getting the range not all the argument were processsed.
+ //
+ if (CurrentArg != Argc) {
+ FwPrint(MON_INVALID_ARGUMENT_COUNT_MSG);
+ return FALSE;
+ }
+ }
+
+ //
+ // Check for proper alignment.
+ //
+ if ((DataSizeMask&Start) || (DataSizeMask&End)) {
+ FwPrint(MON_UNALIGNED_ADDRESS_MSG);
+ return FALSE;
+ } else {
+ //
+ // Set new addresses
+ //
+ DefaultAddress = End;
+ }
+ while (Start < End) {
+ //
+ // Print address of line.
+ //
+ sprintf(Message,"0x%08lx: ",Start);
+ FwPrint(Message);
+ LineLength = End-Start;
+ if (LineLength > 16) {
+ LineLength = 16;
+ }
+ for (i=0;i<LineLength;i+=DataSize) {
+ ExamineValue(Start,&DataLine[i]);
+ Start+=DataSize;
+ }
+ if (DataSize == 1) {
+ //
+ // If bytes display same data in ASCII
+ //
+ VenMoveCursorToColumn(60);
+ for (i=0;i<LineLength;i++) {
+ if (isprint((UCHAR)DataLine[i])) {
+ sprintf(Message,"%c",DataLine[i]);
+ FwPrint(Message);
+ } else {
+ FwPrint(".");
+ }
+ }
+ }
+ FwPrint(FW_CRLF_MSG);
+ }
+ return TRUE;
+}
+
+BOOLEAN
+ZeroCommand(
+ IN PCHAR Argv[],
+ IN PFW_EXCEPTION_FRAME Frame
+ )
+/*++
+
+Routine Description:
+
+ This routine will implement the Zero command given the
+ arguments in the argc,Argv form.
+
+Arguments:
+
+ Argv - array of zero terminated argument strings.
+ Frame - the saved register & exception state.
+
+Return Value:
+
+ Returns TRUE if the command is valid, FALSE otherwise.
+
+--*/
+
+{
+ ULONG Start,End;
+
+ //
+ // Set the right range of addresses. If none specified use last
+ // set of addresses+128.
+ //
+
+ if (Argc == 1) {
+ Start = DefaultAddress;
+ End = Start + 128;
+ } else {
+
+ if (GetAddressRange(Argv,Frame,&Start,&End) == FALSE) {
+ return FALSE;
+ }
+
+ //
+ // if after getting the range not all the argument were processsed, // error.
+ //
+
+ if (CurrentArg != Argc) {
+ FwPrint(MON_INVALID_ARGUMENT_COUNT_MSG);
+ return FALSE;
+ }
+ }
+
+ //
+ // Check for proper alignment.
+ //
+ if ((0xF&Start) || (0xF&End)) {
+ FwPrint(MON_UNALIGNED_ADDRESS_MSG);
+ return FALSE;
+ } else {
+ //
+ // Set new addresses
+ //
+ DefaultAddress = End;
+ }
+ FillVideoMemory(Start,End-Start,0);
+ return TRUE;
+}
+
+BOOLEAN
+DepositValue(
+ IN PCHAR AsciiValue,
+ IN ULONG Address
+ )
+
+/*++
+
+Routine Description:
+
+ This routine writes the converted value to the specified
+ address. DataSize is set to the size of the data to be written.
+
+Arguments:
+
+ AsciiValue - Supplies a pointer to a string that contains an hexadecimal
+ value.
+ Address - Supplies the address where the value is to be written to.
+
+Return Value:
+
+ TRUE if the value is successfully converted.
+ FALSE otherwise.
+
+--*/
+
+{
+// ULONG Value;
+ ULONGLONG Value;
+ PCHAR Terminator;
+
+ //
+ // Convert value to integer
+ //
+
+ Value = strtouq(AsciiValue,&Terminator,16);
+
+ if (*Terminator != '\0') {
+
+ //
+ // Not the whole string was converted.
+ //
+
+ FwPrint(Terminator);
+ FwPrint(MON_INVALID_VALUE_MSG);
+ return FALSE;
+
+ } else {
+ //
+ // Store the value.
+ //
+ switch (DataSize) {
+ case BYTE:*(PUCHAR)Address = (UCHAR)Value;
+ break;
+ case HALF:*(PUSHORT)Address = (USHORT)Value;
+ break;
+ case MON_LONGWORD:*(PULONG)Address = (ULONG)Value;
+ break;
+ case MON_QUAD:*(PULONGLONG)Address = (ULONGLONG)Value;
+ break;
+ }
+ }
+ return TRUE;
+}
+
+BOOLEAN
+DepositCommand(
+ IN PCHAR Argv[],
+ IN PFW_EXCEPTION_FRAME Frame
+ )
+/*++
+
+Routine Description:
+
+ This routine will implement the Deposit command given the
+ arguments in the argc,Argv form.
+
+Arguments:
+
+ Argv - array of zero terminated argument strings.
+ Frame - the saved register & exception state.
+
+Return Value:
+
+ Returns TRUE if the command is valid, FALSE otherwise.
+
+--*/
+
+{
+ ULONG Start;
+
+ if (Argc!=3) {
+ FwPrint(MON_INVALID_ARGUMENT_COUNT_MSG);
+ return FALSE;
+ }
+
+ if (GetAddress(Argv[1],Frame,&Start) == FALSE) {
+ return FALSE;
+ }
+
+ //
+ // Check for proper alignment.
+ //
+
+ if (DataSizeMask & Start) {
+ FwPrint(MON_UNALIGNED_ADDRESS_MSG);
+ return FALSE;
+ }
+
+ if (DepositValue(Argv[2],Start) == TRUE) {
+ //
+ // Set new default addresses
+ //
+ DefaultAddress = Start+DataSize;
+ }
+ return TRUE;
+}
+
+BOOLEAN
+ExamineCommand(
+ IN PCHAR Argv[],
+ IN PFW_EXCEPTION_FRAME Frame
+ )
+/*++
+
+Routine Description:
+
+ This routine will implement the Examine command given the
+ arguments in the argc,Argv form.
+
+Arguments:
+
+ Argv - array of zero terminated argument strings.
+ Frame - the saved register & exception state.
+
+Return Value:
+
+ Returns TRUE if the command is valid, FALSE otherwise.
+
+--*/
+
+{
+ ULONG Start;
+ UCHAR Message[16];
+ ULONG Trash;
+
+ if (Argc!=2) {
+ FwPrint(MON_INVALID_ARGUMENT_COUNT_MSG);
+ return FALSE;
+ }
+
+ if (GetAddress(Argv[1],Frame,&Start) == FALSE) {
+ return FALSE;
+ }
+
+ //
+ // Check for proper alignment.
+ //
+
+ if (DataSizeMask & Start) {
+ FwPrint(MON_UNALIGNED_ADDRESS_MSG);
+ return FALSE;
+ }
+
+ sprintf(Message,"0x%08lx: ",Start);
+ FwPrint(Message);
+ ExamineValue(Start,&Trash);
+ FwPrint(FW_CRLF_MSG);
+
+ //
+ // Set new default addresses
+ //
+
+ DefaultAddress = Start+DataSize;
+ return TRUE;
+}
+
+BOOLEAN
+EnterCommand(
+ IN PCHAR Argv[],
+ IN PFW_EXCEPTION_FRAME Frame
+ )
+/*++
+
+Routine Description:
+
+ This routine will implement the ENTER command given the
+ arguments in the argc,Argv form.
+
+Arguments:
+
+ Argv - array of zero terminated argument strings.
+ Frame - the saved register & exception state.
+
+Return Value:
+
+ Returns TRUE if the command is valid, FALSE otherwise.
+
+--*/
+
+{
+ ULONG Start;
+ CHAR String[32];
+ GETSTRING_ACTION Action;
+
+ //
+ // Set the right range of addresses. If none specified use last
+ // set of addresses+128.
+ //
+
+ switch(Argc) {
+
+ case 1:
+ Start = DefaultAddress;
+ break;
+
+ case 2:
+ if (GetAddress(Argv[1],Frame,&Start) == FALSE) {
+ return FALSE;
+ }
+ break;
+
+ case 3:
+ //
+ // This is equivalent to the Deposit command
+ //
+ return DepositCommand(Argv,Frame);
+
+ default:
+ FwPrint(MON_INVALID_ARGUMENT_COUNT_MSG);
+ return FALSE;
+ }
+
+ //
+ // Check for proper alignment.
+ //
+
+ if (DataSizeMask & Start) {
+ FwPrint(MON_UNALIGNED_ADDRESS_MSG);
+ return FALSE;
+ }
+
+ while (TRUE) {
+
+ //
+ // Print address of line.
+ //
+
+ sprintf(String,"0x%08lx: ",Start);
+ FwPrint(String);
+
+ switch (DataSize) {
+
+ case BYTE:
+ sprintf(String,"%02x . ",*(PUCHAR)Start);
+ break;
+
+ case HALF:
+ sprintf(String,"%04x . ",*(PUSHORT)Start);
+ break;
+
+ case MON_LONGWORD:
+ sprintf(String,"%08lx . ",*(PULONG)Start);
+ break;
+
+ case MON_QUAD:
+ sprintf(String,"%016Lx . ",*(PULONGLONG)Start);
+ break;
+ }
+
+ FwPrint(String);
+
+ do {
+ Action = JzGetString(String, 10, NULL, FwRow+1, FwColumn+1, FALSE);
+ } while ((Action != GetStringSuccess) && (Action != GetStringEscape));
+
+ FwPrint(FW_CRLF_MSG);
+
+ if (String[0] == '\0') { // carriage return exit enter command
+
+ //
+ // set new default address.
+ //
+ DefaultAddress = Start;
+ return TRUE;
+ }
+
+ if (String[0] == ' ') { // blank = next data element.
+ Start+=DataSize;
+ continue;
+ }
+
+ if (String[0] == '-') { // hypen = previous data element.
+ Start-=DataSize;
+ continue;
+ }
+
+ if (DepositValue(String,Start) == TRUE) { // deposit the value.
+ Start+=DataSize;
+ }
+ }
+
+ return TRUE;
+}
+
+BOOLEAN
+FillCommand(
+ IN PCHAR Argv[],
+ IN PFW_EXCEPTION_FRAME Frame
+ )
+/*++
+
+Routine Description:
+
+ This routine will implement the FILL command given the
+ arguments in the argc,Argv form.
+
+ This will remain a longword-based fill for now.
+
+Arguments:
+
+ Argv - array of zero terminated argument strings.
+ Frame - the saved register & exception state.
+
+Return Value:
+
+ Returns TRUE if the command is valid, FALSE otherwise.
+
+--*/
+
+{
+ ULONG Start,End,Values[16];
+ ULONG Index,Count;
+ PCHAR Terminator;
+
+ if (GetAddressRange(Argv,Frame,&Start,&End) == FALSE) {
+ return FALSE;
+ }
+
+ //
+ // if there are no more arguments we don't know what to fill with.
+ //
+
+ if (CurrentArg == Argc) {
+ FwPrint(MON_INVALID_ARGUMENT_COUNT_MSG);
+ return FALSE;
+ }
+
+ //
+ // Convert the values
+ //
+
+ for (Count=0;CurrentArg < Argc; CurrentArg++) {
+ Values[Count++] = strtoul(Argv[CurrentArg],&Terminator,16);
+ if (*Terminator != '\0') {
+ //
+ // Not the whole string was converted.
+ //
+ FwPrint(Terminator);
+ FwPrint(MON_INVALID_VALUE_MSG);
+ return FALSE;
+ }
+ }
+
+ Index = 0;
+ for (;Start < End;Start++) {
+ *((PCHAR)Start) = Values[Index++];
+ if (Index == Count) {
+ Index=0;
+ }
+ }
+
+ return TRUE;
+}
+
+
+VOID
+HelpCommand(
+ VOID
+ )
+/*
+
+Routine Description:
+
+ This outputs a simple command list.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+*/
+
+{
+ ULONG Index;
+
+ for (Index = 0; Index < MON_HELP_SIZE; Index++) {
+ VenPrint(MON_HELP_TABLE[Index]);
+ VenPrint(FW_CRLF_MSG);
+ }
+}
+
+
+BOOLEAN
+FwDumpLookupTable(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This displays the device names stored in the lookup table.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns TRUE if the command is valid, FALSE otherwise.
+
+--*/
+
+{
+ UCHAR C;
+ ULONG Count;
+ PDRIVER_LOOKUP_ENTRY PLookupTable;
+
+ FwPrint(MON_AVAILABLE_HW_DEVICES_MSG);
+
+ PLookupTable=&DeviceLookupTable[0];
+ while (PLookupTable->DevicePath != NULL) {
+ FwPrint(PLookupTable->DevicePath);
+ FwPrint(FW_CRLF_MSG);
+ PLookupTable++;
+ }
+ return(TRUE);
+}
+
+BOOLEAN
+IOReadCommand(
+ IN PCHAR Argv[],
+ IN PFW_EXCEPTION_FRAME Frame
+ )
+
+/*++
+
+Routine Description:
+
+ This implements the IORead command given the arguments in the
+ argc,Argv form. This reads I/O space.
+
+Arguments:
+
+ Argv - array of zero terminated argument strings.
+ Frame - the saved register & exception state.
+
+Return Value:
+
+ Returns TRUE if the command is valid, FALSE otherwise.
+
+--*/
+
+{
+ ULONG Start;
+ UCHAR Message[32];
+
+ if (Argc!=2) {
+ FwPrint(MON_INVALID_ARGUMENT_COUNT_MSG);
+ return FALSE;
+ }
+
+ if (GetAddress(Argv[1],Frame,&Start) == FALSE) {
+ return FALSE;
+ }
+
+ //
+ // Check for proper alignment in I/O space.
+ //
+ if (
+ (// combo space
+ ((Start & 0xf0000000) == 0xa0000000)
+ &&
+ (DataSize != BYTE)
+ )
+ ) {
+ FwPrint(MON_UNALIGNED_ADDRESS_MSG);
+ return FALSE;
+ }
+
+
+ //
+ // Do the I/O space read.
+ //
+ switch (DataSize) {
+
+ // Byte
+ case BYTE:
+ sprintf(Message,"0x%08lx: 0x%02x\r\n",
+ Start,
+ READ_PORT_UCHAR((PUCHAR)Start));
+ FwPrint(Message);
+ break;
+
+ // Word
+ case HALF:
+ sprintf(Message,"0x%08lx: 0x%04x\r\n",
+ Start,
+ READ_PORT_USHORT((PUSHORT)Start));
+ FwPrint(Message);
+ break;
+
+
+ // Longword
+ case MON_LONGWORD:
+ sprintf(Message,"0x%08lx: 0x%08x\r\n",
+ Start,
+ READ_PORT_ULONG((PULONG)Start));
+ FwPrint(Message);
+ break;
+
+ // bad data size
+ default:
+ FwPrint(MON_BAD_IO_OPERATION_MSG);
+ return FALSE;
+ }
+
+
+ //
+ // Set new default addresses
+ //
+ DefaultAddress = Start+DataSize;
+ return TRUE;
+}
+
+#if 0
+
+//
+// The I/O Write commands are disabled in the final product.
+//
+
+BOOLEAN
+IOWriteCommand(
+ IN PCHAR Argv[],
+ IN PFW_EXCEPTION_FRAME Frame
+ )
+
+/*++
+
+Routine Description:
+
+ This implements the IOWrite command given the arguments in the
+ argc,Argv form. This writes I/O space.
+
+Arguments:
+
+ Argv - array of zero terminated argument strings.
+ Frame - the saved register & exception state.
+
+Return Value:
+
+ Returns TRUE if the command is valid, FALSE otherwise.
+
+--*/
+
+{
+ ULONG Start;
+ ULONG Value;
+ UCHAR Message[32];
+ PCHAR Terminator;
+
+ if (Argc!=3) {
+ FwPrint(MON_INVALID_ARGUMENT_COUNT_MSG);
+ return FALSE;
+ }
+
+ if (GetAddress(Argv[1],Frame,&Start) == FALSE) {
+ return FALSE;
+ }
+
+ //
+ // Check for proper alignment in I/O space.
+ //
+ if (// combo space check
+ ((Start & 0xf0000000) == 0xa0000000)
+ &&
+ (DataSize != BYTE)
+ ) {
+ FwPrint(MON_UNALIGNED_ADDRESS_MSG);
+ return FALSE;
+ }
+
+
+ //
+ // Convert deposit value to integer
+ //
+
+ Value = strtoul(Argv[2],&Terminator,16);
+ if (*Terminator != '\0') {
+
+ //
+ // Not the whole string was converted.
+ //
+ FwPrint(Terminator);
+ FwPrint(MON_INVALID_VALUE_MSG);
+ return FALSE;
+
+ } else {
+
+ //
+ // Do the I/O space write
+ //
+ switch (DataSize) {
+
+ // Byte
+ case BYTE:
+ WRITE_PORT_UCHAR((PUCHAR)Start, Value);
+ break;
+
+ // Word
+ case HALF:
+ WRITE_PORT_USHORT((PUSHORT)Start, Value);
+ break;
+
+ // Longword
+ case MON_LONGWORD:
+ WRITE_PORT_ULONG((PULONG)Start, Value);
+ break;
+
+ // bad data size
+ default:
+ FwPrint(MON_BAD_IO_OPERATION_MSG);
+ return FALSE;
+ }
+ }
+
+
+ //
+ // Set new default addresses
+ //
+ DefaultAddress = Start+DataSize;
+ return TRUE;
+}
+
+#endif
+
+
+VOID
+Monitor(
+ IN ULONG CallerSource,
+ IN PFW_EXCEPTION_FRAME Frame
+ )
+/*++
+
+Routine Description:
+
+ This is the main dispatch routine to the various commands
+ that can be typed at the monitor prompt.
+
+
+Arguments:
+
+ For Alpha/Jensen:
+
+ CallerSource 0 if exception (or bugcheck, on Alpha/Jensen)
+ 3 if called from boot menu
+
+ Frame the machine / exception state.
+
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ CHAR Buffer[2][128];
+ ULONG ParityDiag[3];
+ PULONG ParDiag;
+ ULONG BufferIndex;
+ PCHAR Argv[10];
+ PCHAR Tmp;
+ CHAR String[128];
+ BOOLEAN CommandValid;
+ GETSTRING_ACTION Action;
+
+#ifdef ALPHA_FW_KDHOOKS
+
+ //
+ // If this is a breakpoint exception which is recognized, process it.
+ // Otherwise, continue into the Monitor.
+ //
+
+ if ((Frame->ExceptionType == FW_EXC_BPT) &&
+ (FwKdProcessBreakpoint(Frame) == TRUE)) {
+
+ //
+ // This does not return.
+ //
+
+ FwRfe(Frame);
+ }
+
+#endif
+
+ FwPrint(MON_MONITOR_MSG);
+ FwPrint(MON_PRESS_H_MSG);
+
+ //
+ // Initialize command line to null.
+ //
+ Argv[0] = (PCHAR)NULL;
+
+ if (CallerSource !=3) {
+
+ //
+ // Display Cause of exception.
+ //
+
+ if ((Frame->ExceptionType >= FW_EXC_FIRST) &&
+ (Frame->ExceptionType <= FW_EXC_LAST)
+ )
+ { FwPrint(ExceptionNameTable[(Frame->ExceptionType & 0xf)]);}
+ else
+ { FwPrint("** !! Unknown Exception"); }
+
+ FwPrint(MON_EXCEPTION_MSG);
+
+ FwPrint("PC = 0x%016Lx, VA = 0x%016Lx\r\n",
+ Frame->ExceptionFaultingInstructionAddress,
+ Frame->ExceptionVa);
+
+ //
+ // If an exception happened before the ARC console was opened,
+ // a call to JzGetString will not work since JzGetString calls
+ // ArcRead. So, close the console (nothing bad will happen if these
+ // are not already opened) and reopen it.
+ //
+
+ FwClose(ARC_CONSOLE_INPUT);
+ FwClose(ARC_CONSOLE_OUTPUT);
+
+#ifdef ALPHA_FW_KDHOOKS
+
+ //
+ // If we are built with the kernel debugger stubs, and have come
+ // here because of an exception, we want to enter the debugger.
+ //
+
+ Frame->ExceptionType = FW_EXC_BPT;
+ DbgBreakPoint();
+
+#endif
+
+ FwOpenConsole();
+ }
+
+ //
+ // Initialize Static variables.
+ //
+ DefaultAddress = KSEG0_BASE;
+ DataSize = MON_QUAD;
+ BufferIndex = 0;
+
+ //
+ // loop forever getting commands and dispatching them
+ //
+
+ while(TRUE) {
+
+ //
+ // print prompt
+ //
+
+ FwPrint(">");
+
+ //
+ // read a command.
+ //
+
+ do {
+ Action = JzGetString(Buffer[BufferIndex], 128, NULL,
+ FwRow+1, FwColumn+1, FALSE);
+ } while ((Action != GetStringSuccess) && (Action != GetStringEscape));
+ FwPrint(FW_CRLF_MSG);
+
+ //
+ // convert string to lower case.
+ //
+
+ for (Tmp=Buffer[BufferIndex];*Tmp;*Tmp++) {
+ *Tmp=tolower(*Tmp);
+ }
+
+ //
+ // if escape was pressed, simulate a quit command.
+ //
+
+ if (Action == GetStringEscape) {
+ Argc = 1;
+ Argv[0] = "q";
+
+ //
+ // separate command line into tokens delimited by spaces
+ // load up Argv with pointers to arguments and put count in Argc
+ //
+
+ } else if (*Buffer[BufferIndex] != '\0') {
+ Tmp = Buffer[BufferIndex];
+ Argc = 0;
+ //
+ // Skip leading blanks
+ //
+ while ( *Tmp == ' ') {
+ Tmp++;
+ }
+ while ( *Tmp ) {
+ Argv[Argc++] = Tmp;
+ while ( *Tmp ) {
+ if (*Tmp == ' ') {
+ *Tmp++ = '\0';
+ while ( *Tmp == ' ') {
+ Tmp++;
+ }
+ break;
+ }
+ Tmp++;
+ }
+ }
+
+ //
+ // Increment index so that next command is read into the other
+ // buffer. And we preserve the previous one.
+ //
+ BufferIndex = (BufferIndex+1) & 0x1;
+ } else {
+ //
+ // repeat the last command already in Argv Argc
+ //
+ }
+ //
+ // if first argument is not null, then dispatch to routines.
+ //
+ if (Argv[0] != (PCHAR) NULL) {
+ CurrentArg = 1;
+ CurrentCommand = GetCommand(Argv[0]);
+ switch(CurrentCommand) {
+ case DumpByte:
+ case DumpWord:
+ case DumpLongword:
+ case DumpQuad:
+ DataSizeShift = (CurrentCommand - Dump -1);
+ DataSize = 1 << DataSizeShift;
+ DataSizeMask = DataSize-1;
+ case Dump:
+ CommandValid = DumpCommand(Argv,Frame);
+ break;
+
+ case EnterByte:
+ case EnterWord:
+ case EnterLongword:
+ case EnterQuad:
+ DataSizeShift = (CurrentCommand - Enter -1);
+ DataSize = 1 << DataSizeShift;
+ DataSizeMask = DataSize-1;
+ case Enter:
+ CommandValid = EnterCommand(Argv,Frame);
+ break;
+
+ case Help:
+ case Help2:
+ HelpCommand();
+ break;
+
+ case DepositByte:
+ case DepositWord:
+ case DepositLongword:
+ case DepositQuad:
+ DataSizeShift = (CurrentCommand - Deposit -1);
+ DataSize = 1 << DataSizeShift;
+ DataSizeMask = DataSize-1;
+ case Deposit:
+ CommandValid = DepositCommand(Argv,Frame);
+ break;
+ case ExamineByte:
+ case ExamineWord:
+ case ExamineLongword:
+ case ExamineQuad:
+ DataSizeShift = (CurrentCommand - Examine -1);
+ DataSize = 1 << DataSizeShift;
+ DataSizeMask = DataSize-1;
+ case Examine:
+ CommandValid = ExamineCommand(Argv,Frame);
+ break;
+
+ case IOReadByte:
+ case IOReadWord:
+ case IOReadLongword:
+ DataSizeShift = (CurrentCommand - IORead -1);
+ DataSize = 1 << DataSizeShift;
+ DataSizeMask = DataSize-1;
+ case IORead:
+ CommandValid = IOReadCommand(Argv, Frame);
+ break;
+
+#if 0
+
+ case IOWriteByte:
+ case IOWriteWord:
+ case IOWriteLongword:
+ DataSizeShift = (CurrentCommand - IOWrite -1);
+ DataSize = 1 << DataSizeShift;
+ DataSizeMask = DataSize-1;
+ case IOWrite:
+ CommandValid = IOWriteCommand(Argv, Frame);
+ break;
+
+#endif
+
+ case Register:
+ case IntegerRegisterDump:
+ case FloatingRegisterDump:
+ CommandValid = RegisterCommand(Argv, Frame);
+ break;
+
+ case Zero:
+ CommandValid = ZeroCommand(Argv,Frame);
+ break;
+
+ case Fill:
+ CommandValid = FillCommand(Argv,Frame);
+ break;
+
+#if 0
+ case AvailableDevices:
+ CommandValid = FwDumpLookupTable();
+ break;
+#endif
+
+ case Quit:
+ if (CallerSource == 3) {
+ return;
+ } else {
+ //
+ // We came because of an exception.
+ // The only way to exit is reseting the system.
+ //
+ FwPrint(MON_NO_RETURN_MSG);
+ FwPrint(MON_RESET_MACHINE_MSG);
+
+ do {
+ Action = JzGetString(Buffer[BufferIndex],
+ 128,
+ NULL,
+ FwRow+1,
+ FwColumn+1,
+ FALSE);
+ } while ((Action != GetStringSuccess) && (Action != GetStringEscape));
+ FwPrint(FW_CRLF_MSG);
+
+ Buffer[BufferIndex][0]=tolower(Buffer[BufferIndex][0]);
+ if (strcmp(Buffer[BufferIndex],"y") == 0) {
+ ResetSystem();
+ }
+ break;
+ }
+
+ case invalidcommand:
+
+ FwPrint(MON_UNRECOGNIZED_COMMAND_MSG);
+
+ //
+ // Clear the argument so that re-do last command
+ // doesn't repeat the erroneous command.
+ //
+
+ CommandValid = FALSE;
+ break;
+ }
+
+ if (!CommandValid) {
+ Argv[0] = (PCHAR) NULL;
+ }
+ }
+ }
+}
diff --git a/private/ntos/fw/alpha/monitor.h b/private/ntos/fw/alpha/monitor.h
new file mode 100644
index 000000000..394dd01d5
--- /dev/null
+++ b/private/ntos/fw/alpha/monitor.h
@@ -0,0 +1,214 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ monitor.h
+
+Abstract:
+
+ This module contains definitions for monitor.c
+
+Author:
+
+ Lluis Abello (lluis) 09-Sep-1991
+
+Revision History:
+
+ 21-May-1992 John DeRosa [DEC]
+
+ Modified for Alpha and the Alpha-64 calling standard.
+
+--*/
+
+#ifndef _MONITOR_
+#define _MONITOR_
+
+#include "fwpexcpt.h"
+
+
+//
+// Define register names.
+//
+
+typedef enum _REGISTER_NAME_ID {
+ ReservedForExceptionType,
+ exceptparam1, // exception parameter 1
+ exceptparam2, // exception parameter 2
+ exceptparam3, // exception parameter 3
+ exceptparam4, // exception parameter 4
+ exceptparam5, // exception parameter 5
+ exceptpsr, // exception psr
+ exceptmmcsr, // exception mm csr
+ exceptva, // exception va
+ exceptpc, // exception pc
+ v0, // general register 0
+ t0, // general register 1
+ t1, // general register 2
+ t2, // general register 3
+ t3, // general register 4
+ t4, // general register 5
+ t5, // general register 6
+ t6, // general register 7
+ t7, // general register 8
+ s0, // general register 9
+ s1, // general register 10
+ s2, // general register 11
+ s3, // general register 12
+ s4, // general register 13
+ s5, // general register 14
+ fp, // general register 15
+ a0, // general register 16
+ a1, // general register 17
+ a2, // general register 18
+ a3, // general register 19
+ a4, // general register 20
+ a5, // general register 21
+ t8, // general register 22
+ t9, // general register 23
+ t10, // general register 24
+ t11, // general register 25
+ ra, // general register 26
+ t12, // general register 27
+ at, // general register 28
+ gp, // general register 29
+ sp, // general register 30
+ zero, // general register 31
+ f0, // fp register 0
+ f1, // fp register 1
+ f2, // fp register 2
+ f3, // fp register 3
+ f4, // fp register 4
+ f5, // fp register 5
+ f6, // fp register 6
+ f7, // fp register 7
+ f8, // fp register 8
+ f9, // fp register 9
+ f10, // fp register 10
+ f11, // fp register 11
+ f12, // fp register 12
+ f13, // fp register 13
+ f14, // fp register 14
+ f15, // fp register 15
+ f16, // fp register 16
+ f17, // fp register 17
+ f18, // fp register 18
+ f19, // fp register 19
+ f20, // fp register 20
+ f21, // fp register 21
+ f22, // fp register 22
+ f23, // fp register 23
+ f24, // fp register 24
+ f25, // fp register 25
+ f26, // fp register 26
+ f27, // fp register 27
+ f28, // fp register 28
+ f29, // fp register 29
+ f30, // fp register 30
+ f31, // fp register 31
+ invalidregister
+} REGISTER_NAME_ID;
+
+extern PCHAR RegisterNameTable[(REGISTER_NAME_ID)invalidregister];
+
+extern ULONG RegisterTable[(REGISTER_NAME_ID)invalidregister];
+
+//
+// Define Command names.
+//
+// This must match the command table in monitor.c
+//
+
+//
+// I/O Write commands, and Available Devices, have been disabled for
+// the final product.
+//
+
+#if 0
+
+typedef enum _COMMAND_NAME_ID {
+ Dump,
+ DumpByte,
+ DumpWord,
+ DumpLongword,
+ DumpQuad,
+ Enter,
+ EnterByte,
+ EnterWord,
+ EnterLongword,
+ EnterQuad,
+ Help,
+ Help2,
+ Deposit,
+ DepositByte,
+ DepositWord,
+ DepositLongword,
+ DepositQuad,
+ Examine,
+ ExamineByte,
+ ExamineWord,
+ ExamineLongword,
+ ExamineQuad,
+ IORead,
+ IOReadByte,
+ IOReadWord,
+ IOReadLongword,
+ IOWrite,
+ IOWriteByte,
+ IOWriteWord,
+ IOWriteLongword,
+ Register,
+ IntegerRegisterDump,
+ FloatingRegisterDump,
+ Zero,
+ Fill,
+ AvailableDevices,
+ Quit,
+ invalidcommand
+} COMMAND_NAME_ID;
+
+#else
+
+typedef enum _COMMAND_NAME_ID {
+ Dump,
+ DumpByte,
+ DumpWord,
+ DumpLongword,
+ DumpQuad,
+ Enter,
+ EnterByte,
+ EnterWord,
+ EnterLongword,
+ EnterQuad,
+ Help,
+ Help2,
+ Deposit,
+ DepositByte,
+ DepositWord,
+ DepositLongword,
+ DepositQuad,
+ Examine,
+ ExamineByte,
+ ExamineWord,
+ ExamineLongword,
+ ExamineQuad,
+ IORead,
+ IOReadByte,
+ IOReadWord,
+ IOReadLongword,
+ Register,
+ IntegerRegisterDump,
+ FloatingRegisterDump,
+ Zero,
+ Fill,
+ Quit,
+ invalidcommand
+} COMMAND_NAME_ID;
+
+#endif
+
+extern PCHAR CommandNameTable[(COMMAND_NAME_ID)invalidcommand];
+
+#endif // _MONITOR_
diff --git a/private/ntos/fw/alpha/oli2msft.h b/private/ntos/fw/alpha/oli2msft.h
new file mode 100644
index 000000000..2733d4503
--- /dev/null
+++ b/private/ntos/fw/alpha/oli2msft.h
@@ -0,0 +1,39 @@
+
+// ----------------------------------------------------------------------------
+// File: oli2msft.h
+//
+// Description: General type definitions used in C files by Olivetti and
+// not Microsoft
+//
+// ----------------------------------------------------------------------------
+
+typedef ULONG BOOLEAN_ULONG;
+typedef BOOLEAN_ULONG *PBOOLEAN_ULONG;
+
+//
+// Configuration related defines
+//
+
+#define MAX_MNEMONIC_LEN 20 // max name length (with '\0')
+#define MAX_DEVICE_PATH_LEN 63 // ending '\0' excluded
+#define MAX_FILE_PATH_LEN 127 // ending '\0' excluded
+#define MAX_PATH_LEN (MAX_DEVICE_PATH_LEN + MAX_FILE_PATH_LEN)
+#define KEY_MAX_DIGITS 4 // max digits within a "key
+ // string" (\'0' not included).
+//
+// Configuration Data Header
+//
+
+typedef struct _CONFIGDATAHEADER
+ {
+ USHORT Version;
+ USHORT Revision;
+ PCHAR Type;
+ PCHAR Vendor;
+ PCHAR ProductName;
+ PCHAR SerialNumber;
+ } CONFIGDATAHEADER, *PCONFIGDATAHEADER;
+
+#define CONFIGDATAHEADER_SIZE sizeof(CONFIGDATAHEADER)
+
+#define MAXIMUM_SECTOR_SIZE 2048 // # bytes per sector
diff --git a/private/ntos/fw/alpha/omf.c b/private/ntos/fw/alpha/omf.c
new file mode 100644
index 000000000..50455af6e
--- /dev/null
+++ b/private/ntos/fw/alpha/omf.c
@@ -0,0 +1,3794 @@
+// ----------------------------------------------------------------------------
+//
+// Copyright (c) 1992 Olivetti
+//
+// File: omf.c
+//
+// Description: this code implements the omf protocol as defined
+// in the ARC-EISA addendum.
+//
+// ----------------------------------------------------------------------------
+
+#include "fwp.h"
+#include "oli2msft.h"
+#include "arceisa.h"
+#include "inc.h"
+#include "string.h"
+#include "debug.h"
+
+extern BL_FILE_TABLE BlFileTable [BL_FILE_TABLE_SIZE];
+
+#define DEVICE_DEVICE 0xDEAD
+
+
+// ----------------------------------------------------------------------------
+// Declare Function Prototypes
+// ----------------------------------------------------------------------------
+
+ARC_STATUS
+OmfOpen
+ (
+ IN PCHAR OpenPath,
+ IN OPEN_MODE OpenMode,
+ IN OUT PULONG FileId
+ );
+
+ARC_STATUS
+OmfClose
+ (
+ IN ULONG FileId
+ );
+
+ARC_STATUS
+OmfMount
+ (
+ IN PCHAR MountPath,
+ IN MOUNT_OPERATION Operation
+ );
+
+ARC_STATUS
+OmfRead
+ (
+ IN ULONG FileId,
+ IN PVOID Buffer,
+ IN ULONG Length,
+ OUT PULONG Count
+ );
+
+ARC_STATUS
+OmfWrite
+ (
+ IN ULONG FileId,
+ IN PVOID Buffer,
+ IN ULONG Length,
+ OUT PULONG Count
+ );
+
+ARC_STATUS
+OmfGetReadStatus
+ (
+ IN ULONG FileId
+ );
+
+ARC_STATUS
+OmfSeek
+ (
+ IN ULONG FileId,
+ IN PLARGE_INTEGER Offset,
+ IN SEEK_MODE SeekMode
+ );
+
+ARC_STATUS
+OmfGetFileInformation
+ (
+ IN ULONG FileId,
+ OUT PFILE_INFORMATION Buffer
+ );
+
+ARC_STATUS
+OmfSetFileInformation
+ (
+ IN ULONG FileId,
+ IN ULONG AttributeFlags,
+ IN ULONG AttributeMask
+ );
+
+ARC_STATUS
+OmfGetDirectoryEntry
+ (
+ IN ULONG FileId,
+ IN DIRECTORY_ENTRY *DirEntry,
+ IN ULONG NumberDir,
+ OUT PULONG CountDir
+ );
+
+ARC_STATUS
+OmfFileOpen
+ (
+ IN PCHAR OpenPath,
+ IN OPEN_MODE OpenMode,
+ IN OUT PULONG FileId
+ );
+
+ARC_STATUS
+OmfFileClose
+ (
+ IN ULONG FileId
+ );
+
+ARC_STATUS
+OmfFileMount
+ (
+ IN PCHAR MountPath,
+ IN MOUNT_OPERATION Operation
+ );
+
+ARC_STATUS
+OmfFileRead
+ (
+ IN ULONG FileId,
+ IN PVOID Buffer,
+ IN ULONG Length,
+ OUT PULONG Count
+ );
+
+ARC_STATUS
+OmfFileWrite
+ (
+ IN ULONG FileId,
+ IN PVOID Buffer,
+ IN ULONG Length,
+ OUT PULONG Count
+ );
+
+ARC_STATUS
+OmfFileGetReadStatus
+ (
+ IN ULONG FileId
+ );
+
+ARC_STATUS
+OmfFileSeek
+ (
+ IN ULONG FileId,
+ IN PLARGE_INTEGER Offset,
+ IN SEEK_MODE SeekMode
+ );
+
+ARC_STATUS
+OmfFileGetFileInformation
+ (
+ IN ULONG FileId,
+ OUT PFILE_INFORMATION Buffer
+ );
+
+ARC_STATUS
+OmfFileSetFileInformation
+ (
+ IN ULONG FileId,
+ IN ULONG AttributeFlags,
+ IN ULONG AttributeMask
+ );
+
+ARC_STATUS
+OmfFileGetDirectoryEntry
+ (
+ IN ULONG FileId,
+ IN DIRECTORY_ENTRY *DirEntry,
+ IN ULONG NumberDir,
+ OUT PULONG CountDir
+ );
+
+BOOLEAN
+MaxOmfFatFiles
+ (
+ IN OUT PCHAR MasterName,
+ IN PCHAR CheckedName
+ );
+
+BOOLEAN
+OmfFileNameValidate
+ (
+ IN PCHAR OpenPath,
+ OUT PCHAR OmfFileName,
+ OUT PCHAR OmfType
+ );
+
+BOOLEAN
+CmpOmfFiles
+ (
+ IN PCHAR OmfFileName,
+ IN CHAR OmfType,
+ IN POMF_DIR_ENT POmfDirEnt
+ );
+
+BOOLEAN
+OmfHeaderValidate
+ (
+ IN ULONG FileId
+ );
+
+BOOLEAN
+OmfFileValidate
+ (
+ IN ULONG FileId
+ );
+
+VOID
+ConvertOmfDirToArcDir
+ (
+ IN POMF_DIR_ENT POmfDirEnt,
+ OUT DIRECTORY_ENTRY *PArcDirEnt
+ );
+
+BOOLEAN
+FwGetEisaId
+ (
+ IN PCHAR PathName,
+ OUT PCHAR EisaId,
+ OUT PUCHAR IdInfo
+ );
+
+VOID
+FwUncompressEisaId
+ (
+ IN PUCHAR CompEisaId,
+ OUT PUCHAR UncompEisaId
+ );
+
+BOOLEAN
+FwGetEisaBusIoCpuAddress
+ (
+ IN PCHAR EisaPath,
+ OUT PVOID *IoBusAddress
+ );
+
+PCHAR
+FwGetEnvironmentVariable
+ (
+ IN PCHAR Variable
+ );
+
+PCONFIGURATION_COMPONENT
+FwGetComponent
+ (
+ IN PCHAR Pathname
+ );
+
+LARGE_INTEGER
+RtlConvertUlongToLargeInteger
+ (
+ IN ULONG UnsignedInteger
+ );
+
+LARGE_INTEGER
+RtlLargeIntegerAdd
+ (
+ IN LARGE_INTEGER Addend1,
+ IN LARGE_INTEGER Addend2
+ );
+
+ARC_STATUS
+FwFileIdChecksum
+ (
+ IN ULONG FileId,
+ IN LARGE_INTEGER StartingOffset,
+ IN ULONG Length,
+ IN OUT PUCHAR Checksum
+ );
+
+BOOLEAN
+FwGetMnemonicKey
+ (
+ IN PCHAR Path,
+ IN PCHAR Mnemonic,
+ IN PULONG Key
+ );
+
+BOOLEAN
+FwGetNextMnemonic
+ (
+ IN PCHAR Path,
+ IN PCHAR Mnemonic,
+ OUT PCHAR NextMnemonic
+ );
+
+BOOLEAN
+FwGetMnemonicPath
+ (
+ IN PCHAR Path,
+ IN PCHAR Mnemonic,
+ OUT PCHAR MnemonicPath
+ );
+
+BOOLEAN
+GetNextPath
+ (
+ IN OUT PCHAR *PPathList,
+ OUT PCHAR PathTarget
+ );
+
+
+// ----------------------------------------------------------------------------
+// Global Data
+// ----------------------------------------------------------------------------
+
+//
+// Omf entry table.
+// This is a structure that provides entry to the OMF system procedures.
+// It is exported when a OMF is opened as a device.
+//
+
+BL_DEVICE_ENTRY_TABLE OmfEntryTable =
+ {
+ OmfClose,
+ OmfMount,
+ OmfOpen,
+ OmfRead,
+ OmfGetReadStatus,
+ OmfSeek,
+ OmfWrite,
+ OmfGetFileInformation,
+ OmfSetFileInformation,
+ NULL,
+ OmfGetDirectoryEntry
+ };
+
+
+//
+// Omf file entry table.
+// This is a structure that provides entry to the OMF file system procedures.
+// It is exported when a OMF file is opened.
+//
+
+BL_DEVICE_ENTRY_TABLE OmfFileEntryTable =
+ {
+ OmfFileClose,
+ OmfFileMount,
+ OmfFileOpen,
+ OmfFileRead,
+ OmfFileGetReadStatus,
+ OmfFileSeek,
+ OmfFileWrite,
+ OmfFileGetFileInformation,
+ OmfFileSetFileInformation,
+ NULL,
+ OmfFileGetDirectoryEntry
+ };
+
+
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: OmfOpen:
+//
+// DESCRIPTION: The routine opens the newest version/revision of OMF for
+// the specified Product ID.
+//
+// a) It reads the EISAROM bit of the <device> component of
+// the Path argument on the EISA bus spcified by the key of
+// the <adapter> component of Path argument.
+// b) If this bit is one, then a byte checksum is performed on
+// the ROM-based OMF header and OMF directory.
+// The Product ID, Firmware Version and Revision fields
+// values are retained for the next operations.
+// c) Next, the partitions, specified by the FWSearchPath
+// environment variable are searched for files of the
+// following form in the \eisa\omf subdirectory:
+//
+// <device>"V".LF"R"
+//
+// <device> = EISA Product ID (7 chars)
+// "V" = version ([0-9],[A-Z])
+// "R" = revision ([0-9],[A-Z])
+//
+// d) The OMF FAT file (or ROM) with a greater value of version-
+// revision and with a correct checksum is used.
+// f) Initialize some data structures
+//
+// When Open is used to access an OMF as a raw device, all input
+// functions are permitted. These functions include Read, Seek
+// and Close. Read and Seek are bounded by the current OMF size.
+// For example, to read the OMF of a serial options board that was
+// in slot 3 of EISA bus 0 as raw device, create and Open a path
+// as follows: eisa(0)serial(3)omf() .
+//
+// ARGUMENTS: OpenPath Supplies a pointer to a zero terminated device
+// path name.
+// OpenMode Supplies the mode of the open.
+// FileId Supplies a pointer to a variable that specifies
+// the file table entry that is to be filled in
+// if the open is successful.
+//
+// RETURN: ESUCCESS is returned if the open operation is successful.
+// ENODEV the device portion of the pathname is invalid
+//
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+// ----------------------------------------------------------------------------
+//
+
+ARC_STATUS
+OmfOpen
+ (
+ IN PCHAR OpenPath,
+ IN OPEN_MODE OpenMode,
+ IN OUT PULONG FileId
+ )
+{
+ //
+ // initialize local variables
+ //
+
+ LARGE_INTEGER Offset; // large interger for seek operations
+ ULONG SlotNumber; // eisa slot number
+ CHAR EisaCtrlMnemonic[ MAX_MNEMONIC_LEN +1 ]; // eisa ctrl mnemonic name
+ UCHAR IdInfo; // info id byte
+ PVOID IoBusAddress; // eisa I/O base address (virtual)
+ PUCHAR SlotAddress; // I/O address
+ BOOLEAN OmfRomOk=FALSE; // OMF ROM initialization flag
+ BOOLEAN OmfFatFileOk=FALSE; // OMF FAT file initialization flag
+ ULONG Count; // # of bytes transferred
+ PCHAR PFwSearchPath; // system partitions list pointer
+ CHAR OmfPathName[MAX_PATH_LEN +1]; // directory+subdirectory+file name
+ CHAR OmfPathBuffer[MAX_PATH_LEN +1] = {'\0'}; // OMF path name buffer
+ CHAR OmfFatFileName[]=" .LF "; // omf name (FAT format)
+
+ ULONG OmfSubdirId; // file Id of \eisa\omf subdirectory
+ POMF_HEADER_CONTEXT POmfHeaderContext; // OMF header context pointer
+ POMF_HDR POmfHeader; // pointer to OMF ROM/FAT file header
+ DIRECTORY_ENTRY DirEntBuffer; // ARC directory entry
+
+ PRINTDBG("OmfOpen\n\r"); // debug support
+
+ //
+ // this is a read only device
+ //
+
+ if ( OpenMode != ArcOpenReadOnly )
+ {
+ return EROFS;
+ }
+
+ //
+ // The path must have the following form : eisa(x)"mnemonic"(y)omf()
+ // Get EISA ID, slot number and its I/O address space.
+ //
+
+ if ( !FwGetNextMnemonic( OpenPath, "eisa", EisaCtrlMnemonic )
+ ||
+ !FwGetMnemonicKey( OpenPath, EisaCtrlMnemonic, &SlotNumber )
+ ||
+ !FwGetMnemonicPath( OpenPath, EisaCtrlMnemonic, OmfPathName )
+ ||
+ !FwGetEisaId( OmfPathName, OmfFatFileName, &IdInfo )
+ ||
+ !FwGetMnemonicPath( OpenPath,"eisa",OmfPathName )
+ ||
+ !FwGetEisaBusIoCpuAddress( OmfPathName, &IoBusAddress ) )
+ {
+ return ENODEV;
+ }
+
+ //
+ // Initialize some variables
+ //
+
+ POmfHeaderContext = &BlFileTable[ *FileId ].u.OmfHeaderContext;
+ POmfHeader = &POmfHeaderContext->OmfHeader;
+ SlotAddress = (PUCHAR)IoBusAddress + SlotNumber * 0x1000;
+ Offset.LowPart = 0; // seek operation
+ Offset.HighPart = 0; // seek operation
+
+ //
+ // Check EISAROM bit of the Expansion Board Control Bits field.
+ // If the EISA ID is readable, the controller supports the EISA extensions
+ //
+
+ // DEBUG-DEBUG : for now skip the OMF ROM check because
+ // at the moment there isn't any board available
+ // with an OMF ROM to test the routine.
+
+#if 0
+ if ( !(IdInfo & CFG_UNREADABLE_ID) &&
+ READ_PORT_UCHAR( SlotAddress + EXPANSION_BOARD_CTRL_BITS ) &
+ EISAROMBIT )
+ {
+ //
+ // initialize some fields to direct the OmfRead to the ROM
+ //
+
+ POmfHeaderContext->RomIndex = (PULONG)(SlotAddress+ROMINDEX);
+ POmfHeaderContext->RomRead = (PULONG)(SlotAddress+ROMREAD);
+ POmfHeaderContext->FileId = DEVICE_DEVICE;
+ POmfHeader->FwSize = 0; // max length simulation
+
+ //
+ // check OMF ROM header, copy it in the OmfHeaderContext structure
+ //
+
+ if ( !OmfSeek( *FileId, &Offset, SeekAbsolute)
+ &&
+ !OmfRead( *FileId,
+ (PVOID)POmfHeader,
+ (ULONG)sizeof(OMF_HDR),
+ &Count )
+ &&
+ OmfHeaderValidate( *FileId ) )
+ {
+ //
+ // copy version and revision
+ //
+
+ ((POMF_FAT_FILE_NAME)OmfFatFileName)->Version =
+ POmfHeader->FwVersion;
+ ((POMF_FAT_FILE_NAME)OmfFatFileName)->Revision =
+ POmfHeader->FwRevision;
+ //
+ // OMF ROM initialization has been done
+ //
+
+ OmfRomOk=TRUE;
+ }
+ }
+#endif
+
+ //
+ // Set the current FileId to "open" so that calls to FwOpen won't use
+ // this FileId. This will get reset later.
+ //
+
+ BlFileTable[ *FileId ].Flags.Open = 1;
+
+ //
+ // check now if there is any file that upgrades the OFM ROM firmware.
+ // the partitions, specified by the FWSearchPath environment variable,
+ // are searched for files of the following form in the \eisa\omf
+ // subdirectory:
+ // <device>"V".LF"R"
+ //
+ // <device> = EISA Product ID (7 chars)
+ // "V" = version ([0-9],[A-Z])
+ // "R" = revision ([0-9],[A-Z])
+ //
+
+ if ( (PFwSearchPath = FwGetEnvironmentVariable("FWSearchPath")) != NULL )
+ {
+ //
+ // check all the directories specified by FWSearchPath
+ //
+
+ while ( GetNextPath( &PFwSearchPath, OmfPathName ))
+ {
+ //
+ // open the directory
+ //
+
+ strcat(OmfPathName, "\\eisa\\omf" );
+
+ if ( FwOpen( OmfPathName, ArcOpenDirectory, &OmfSubdirId ))
+ {
+ //
+ // Go check next path
+ //
+
+ continue;
+ }
+
+ //
+ // Check all files within the directory
+ //
+
+ while (!FwGetDirectoryEntry ( OmfSubdirId, &DirEntBuffer,
+ (ULONG) 1, &Count) )
+ {
+ //
+ // check directory flag, length of file name and file name
+ //
+
+ if ( !( DirEntBuffer.FileAttribute & ArcDirectoryFile )
+ &&
+ DirEntBuffer.FileNameLength
+ &&
+ MaxOmfFatFiles( OmfFatFileName, DirEntBuffer.FileName ))
+ {
+ //
+ // correct name, save file path
+ //
+
+ strcat( strcpy(OmfPathBuffer, OmfPathName), "\\" );
+ strcat(OmfPathBuffer, OmfFatFileName);
+ }
+ }
+
+ //
+ // close directory before opening the next
+ //
+
+ FwClose( OmfSubdirId );
+ }
+ }
+
+ //
+ // check for a valid OMF FAT file name
+ //
+
+ if ( OmfPathBuffer[0] )
+ {
+ //
+ // open file
+ //
+
+ if (FwOpen(OmfPathBuffer, ArcOpenReadOnly, &POmfHeaderContext->FileId))
+ {
+ //
+ // return with error
+ //
+
+ BlFileTable[ *FileId ].Flags.Open = 0;
+ return ENODEV;
+ }
+
+ POmfHeader->FwSize=0; // max length simulation
+
+ //
+ // validate header and copy data in the OmfHeaderContext structure
+ //
+
+ if ( OmfSeek( *FileId, &Offset, SeekAbsolute )
+ ||
+ OmfRead( *FileId,
+ (PVOID)POmfHeader,
+ (ULONG)sizeof(OMF_HDR),
+ &Count)
+ ||
+ !OmfHeaderValidate( *FileId ) )
+ {
+
+ PRINTDBG("No OK\n\r");
+
+ //
+ // close file and return with error
+ //
+
+ FwClose(POmfHeaderContext->FileId);
+ BlFileTable[ *FileId ].Flags.Open = 0;
+ return ENODEV;
+ }
+
+ //
+ // OMF FAT file initialization is done.
+ //
+
+ PRINTDBG("It's OK\n\r");
+
+ OmfFatFileOk=TRUE;
+ }
+
+ //
+ // Reset the open flag.
+ //
+
+ BlFileTable[ *FileId ].Flags.Open = 0;
+
+ //
+ // if OMF initialization not done, return error
+ //
+
+// if ( !OmfRomOk && !OmfFatFileOk )
+ if ( !OmfFatFileOk )
+ {
+ return ENOENT;
+ }
+ else
+ {
+ BlFileTable[ *FileId ].Position.LowPart=0;
+ BlFileTable[ *FileId ].Position.HighPart=0;
+ return ESUCCESS;
+ }
+}
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: OmfClose:
+//
+// DESCRIPTION: The routine closes the file table entry specified by file id.
+// If a OMF FAT file has been used, the routine calls the FwClose
+// function using its file table entry (file id).
+// the routine uses the following logic :
+//
+// if (OMF FAT file)
+// {
+// close file;
+// if (error closing file)
+// return error;
+// }
+// reset open flag;
+// return ok;
+//
+// ARGUMENTS: FileId Supplies a pointer to a variable that specifies
+// the file table entry.
+//
+// RETURN: ESUCCESS is returned if the open operation is successful.
+// EBADF invalid file descriptor
+//
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+// ----------------------------------------------------------------------------
+//
+
+ARC_STATUS
+OmfClose
+ (
+ IN ULONG FileId
+ )
+{
+ //
+ // initialize local variables
+ //
+
+ ARC_STATUS Status; // store return status from FwClose
+
+ //
+ // if OMF FAT file is used, call FwClose using its file table index
+ //
+
+ PRINTDBG("OmfClose\n\r");
+
+ if ( BlFileTable[ FileId ].DeviceId != DEVICE_DEVICE)
+ {
+ return EBADF;
+ }
+
+ if ( BlFileTable[ FileId ].u.OmfHeaderContext.FileId != DEVICE_DEVICE
+ &&
+ (Status = FwClose( BlFileTable[ FileId ].u.OmfHeaderContext.FileId)))
+ {
+ return Status;
+ }
+
+ //
+ // all done, return ok
+ //
+
+ BlFileTable[ FileId ].Flags.Open = 0;
+ return ESUCCESS;
+}
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: OmfMount:
+//
+// DESCRIPTION: The routine does nothing and return EBADF.
+//
+// ARGUMENTS: MountPath device path specifier.
+// Operation mount operation (load/unload).
+//
+// RETURN: EBADF invalid operation
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+// ----------------------------------------------------------------------------
+//
+
+ARC_STATUS
+OmfMount
+ (
+ IN PCHAR MountPath,
+ IN MOUNT_OPERATION Operation
+ )
+{
+ //
+ // return error : invalid operation.
+ //
+
+ return EBADF;
+}
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: OmfRead:
+//
+// DESCRIPTION: This routine implements the read operation for the ARC-EISA
+// firmware "OMF" driver.
+//
+// ARGUMENTS: FileId Supplies a pointer to a variable that specifies
+// the file table entry.
+// Buffer Supplies a pointer to a buffer where the
+// characters read will be stored.
+// Length Supplies the length of Buffer.
+// Count Return the count of the characters that
+// were read.
+//
+// RETURN: ESUCCESS is returned if the open operation is successful.
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+// ----------------------------------------------------------------------------
+//
+
+ARC_STATUS
+OmfRead
+ (
+ IN ULONG FileId,
+ IN PVOID Buffer,
+ IN ULONG Length,
+ OUT PULONG Count
+ )
+{
+
+ //
+ // initialize local variables
+ //
+
+ ARC_STATUS Status; // ARC status
+ POMF_HEADER_CONTEXT POmfHeaderContext; // OMF header context pointer
+ ULONG OmfSize; // OMF firmware size (bytes)
+ PLARGE_INTEGER PPosition; // file/device position field pointer
+ USHORT ByteIndex; // byte index within the word
+ ULONG WordBuffer; // 1 word buffer
+
+
+ PRINTDBG("OmfRead\n\r");
+
+ //
+ // Initialize some variables
+ //
+
+ POmfHeaderContext = &BlFileTable[ FileId ].u.OmfHeaderContext;
+
+ //
+ // compute OMF length in bytes
+ //
+
+ OmfSize = (ULONG)POmfHeaderContext->OmfHeader.FwSize * OMF_BLOCK_SIZE;
+
+ if ( !OmfSize )
+ {
+ OmfSize = OMF_MAX_SIZE;
+ }
+
+ //
+ // initialize byte count read to zero and position variable
+ //
+
+ *Count = 0;
+ PPosition = &BlFileTable[ FileId ].Position;
+
+ //
+ // if length is zero or end of "file", return ESUCCESS.
+ //
+
+ if ( !Length || PPosition->LowPart >= OmfSize )
+ {
+ return ESUCCESS;
+ }
+
+ //
+ // adjust length if it is too big.
+ //
+
+ Length = MIN( Length, OmfSize ); // to prevent the add to overflow
+
+ if ( PPosition->LowPart + Length > OmfSize )
+ {
+ Length = OmfSize - PPosition->LowPart;
+ }
+
+ //
+ // if OMF FAT file, read from file.
+ //
+
+ if ( POmfHeaderContext->FileId != DEVICE_DEVICE )
+ {
+ if ( !(Status = FwSeek( POmfHeaderContext->FileId,
+ PPosition,
+ SeekAbsolute ))
+ &&
+ !(Status = FwRead( POmfHeaderContext->FileId,
+ Buffer,
+ Length,
+ Count )) )
+ {
+ PPosition->LowPart += *Count;
+ }
+ return Status;
+ }
+
+ //
+ // write word index and compute starting byte index (within a word)
+ //
+
+ WRITE_PORT_ULONG(POmfHeaderContext->RomIndex,
+ PPosition->LowPart >> WORD_2P2 );
+
+ //
+ // read OMF ROM
+ // one loop per word
+ //
+
+ while ( Length )
+ {
+ ByteIndex = (USHORT) (PPosition->LowPart & (1<<WORD_2P2)-1);
+
+ //
+ // read the whole word if the buffer and OMF pointers are
+ // word aligned.
+ // // |
+ if ( !ByteIndex // DEBUG V
+ &&
+ !((USHORT)((PUCHAR)Buffer + *Count) & (1 << WORD_2P2) -1 ) )
+ {
+ while ( Length >= (1 << WORD_2P2) )
+ {
+ *((PULONG)( (PUCHAR)Buffer + *Count ))=
+ READ_PORT_ULONG( POmfHeaderContext->RomRead );
+ *Count += 1<<WORD_2P2;
+ Length -= 1<<WORD_2P2;
+ }
+ }
+
+ //
+ // read the word in bytes units if the buffer or the OMF pointers
+ // are not word aligned or if just part of the word is needed.
+ //
+
+ if ( Length )
+ {
+ WordBuffer = READ_PORT_ULONG( POmfHeaderContext->RomRead );
+
+ //
+ // read just the selected bytes
+ //
+
+ while ( ByteIndex < (1 << WORD_2P2) && Length-- )
+ {
+ *( (PUCHAR)Buffer + *Count++ )=
+ (UCHAR)( WordBuffer >> BITSXBYTE * ByteIndex++ );
+ }
+ }
+
+ //
+ // update OMF pointer
+ //
+
+ PPosition->LowPart += *Count;
+ }
+
+ //
+ // return all done
+ //
+
+ return ESUCCESS;
+}
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: OmfWrite:
+//
+// DESCRIPTION: This routine implements the write operation for the ARC-EISA
+// firmware "OMF" driver.
+//
+// ARGUMENTS: FileId Supplies a pointer to a variable that specifies
+// the file table entry.
+// Buffer Supplies a pointer to a buffer where the
+// characters are read.
+// Length Supplies the length of Buffer.
+// Count Return the count of the characters that
+// were written.
+//
+// RETURN: EBADF invalid operation
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+// ----------------------------------------------------------------------------
+//
+
+ARC_STATUS
+OmfWrite
+ (
+ IN ULONG FileId,
+ IN PVOID Buffer,
+ IN ULONG Length,
+ OUT PULONG Count
+ )
+{
+ //
+ // return error : invalid operation
+ //
+
+ return EBADF;
+}
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: OmfGetReadStatus:
+//
+// DESCRIPTION: This routine implements the GetReadStatus operation for the
+// ARC-EISA firmware "OMF" driver.
+//
+// ARGUMENTS: FileId Supplies a pointer to a variable that specifies
+// the file table entry.
+//
+// RETURN: ESUCCESS return always success.
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+// ----------------------------------------------------------------------------
+//
+
+ARC_STATUS
+OmfGetReadStatus
+ (
+ IN ULONG FileId
+ )
+{
+ //
+ // return ok
+ //
+
+ return ESUCCESS;
+}
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: OmfSeek:
+//
+// DESCRIPTION: This routine implements the Seek operation for the
+// ARC-EISA firmware "OMF" driver.
+//
+// ARGUMENTS: FileId Supplies a pointer to a variable that specifies
+// the file table entry.
+// Offset Supplies the offset in the file to position to.
+// SeekMode Supplies the mode of the seek operation
+//
+// RETURN: ESUCCESS returned if the operation is successful.
+// EINVAL returned otherwise.
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+// ----------------------------------------------------------------------------
+//
+
+ARC_STATUS
+OmfSeek
+ (
+ IN ULONG FileId,
+ IN PLARGE_INTEGER Offset,
+ IN SEEK_MODE SeekMode
+ )
+{
+ //
+ // local variables
+ //
+
+ LARGE_INTEGER Point; // New position
+ ULONG OmfSize; // OMF size in bytes
+
+ PRINTDBG("OmfSeek\n\r");
+
+ //
+ // initialize some variables
+ //
+
+ OmfSize = (ULONG)BlFileTable[ FileId ].u.OmfHeaderContext.OmfHeader.FwSize *
+ OMF_BLOCK_SIZE;
+
+ if ( !OmfSize )
+ {
+ OmfSize=OMF_MAX_SIZE;
+ }
+
+ //
+ // compute new offset value
+ //
+
+ switch( SeekMode )
+ {
+ case SeekAbsolute:
+ Point = *Offset;
+ break;
+ case SeekRelative:
+ Point = RtlLargeIntegerAdd( BlFileTable[FileId].Position, *Offset );
+ break;
+ default:
+ return EINVAL;
+ }
+
+ //
+ // if the high 32 bits are not zero, return an error.
+ // if new offset is valid, update position field.
+ // if the position value 0-based is equal to the OMF size (1-based),
+ // the EOF has been reached. no error is returned in this case and
+ // the count field is set to zero with ESUCCESS error code for any
+ // successive read operation. note that this combination (ESUCCESS and
+ // count=0) is used to rappresent EOF (end of file).
+ //
+
+ if ( Point.HighPart || Point.LowPart > OmfSize )
+ {
+ return EINVAL;
+ }
+ else
+ {
+ BlFileTable[FileId].Position = Point;
+ return ESUCCESS;
+ }
+}
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: OmfGetFileInformation:
+//
+// DESCRIPTION: This routine implements the GetFileInformation for the
+// ARC-EISA firmware "OMF" driver.
+//
+// ARGUMENTS: FileId Supplies the file table index.
+// Buffer Supplies the buffer to receive the file
+// information. Note that it must be large
+// enough to hold the full file name.
+//
+// RETURN: EBADF invalid operation
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+// ----------------------------------------------------------------------------
+//
+
+ARC_STATUS
+OmfGetFileInformation
+ (
+ IN ULONG FileId,
+ OUT PFILE_INFORMATION Buffer
+ )
+{
+ //
+ // return error : invalid operation
+ //
+
+ return EBADF;
+}
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: OmfSetFileInformation:
+//
+// DESCRIPTION: This routine implements the SetFileInformation for the
+// ARC-EISA firmware "OMF" driver.
+//
+// ARGUMENTS: FileId Supplies the file table index.
+// AttributeFlags Supplies the value (on or off) for each
+// attribute being modified.
+// AttributeMask Supplies a mask of the attributes being altered.
+// All other file attributes are left alone.
+//
+// RETURN: EBADF invalid operation
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+// ----------------------------------------------------------------------------
+//
+
+ARC_STATUS
+OmfSetFileInformation
+ (
+ IN ULONG FileId,
+ IN ULONG AttributeFlags,
+ IN ULONG AttributeMask
+ )
+{
+ //
+ // return error : invalid operation
+ //
+
+ return EBADF;
+}
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: OmfGetDirectoryEntry:
+//
+// DESCRIPTION: This routine implements the GetDirectoryEntry for the
+// ARC-EISA firmware "OMF" driver.
+//
+// ARGUMENTS: FileId Supplies the file table index.
+// DirEntry Pointer to a directory entry structure
+// NumberDir # of entries to read
+// Count # of entries read
+//
+// RETURN: EBADF directory operations are not supported
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+// ----------------------------------------------------------------------------
+//
+
+ARC_STATUS
+OmfGetDirectoryEntry
+ (
+ IN ULONG FileId,
+ IN DIRECTORY_ENTRY *DirEntry,
+ IN ULONG NumberDir,
+ OUT PULONG CountDir
+ )
+{
+ //
+ // return error : directory operations are not supported
+ //
+
+ return EBADF;
+}
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: OmfFileOpen:
+//
+// DESCRIPTION: The routine opens the OMF file.
+// The <extension> of the <filename> is optional. The caller can
+// make the following assumptions if the <extension> is not
+// included in the <filename> :
+// . the firmware searches for folders whose type is MIPS first.
+// This is equivalent to using '.A' as the <extension>. If
+// the requested folder of this type is found in the most recent
+// OMF, then this folder is used.
+// . If the modst recent OMF does not contain the requested folder
+// whose type is MIPS, then the SMF searches for the requested
+// folder whose type is BINARY. This is equivalent to using '.B'
+// as the <extension>. If the requested folder of this type is
+// found in the most recent OMF then this folder is used.
+// . If there are no folders with either type in the most recent
+// OMF, the operation fails.
+//
+// When omf() is used as <protocol spec> and the filename is the
+// string "\", the path specification represents the OMF directory.
+// The only valid operation to perform on the OMF directory is to
+// Open it, then use FwGetDirectoryEntry to enumerate the folders
+// within the OMF, and then Close it. For example, to
+// enumerate all folders that are containded in the OMF of a
+// serail options board that was in slot 3 of EISA bus0, create
+// and Open a path as follows : eisa(0)serial(3)omf()\ .
+// To open the diagnostic folder for the above EISA option board
+// the system utilty would create and Open the path specification :
+// eisa(0)serial(3)omf()\T-SERIAL.
+//
+//
+// ARGUMENTS: OpenPath Supplies a pointer to a zero terminated OMF
+// file name.
+// OpenMode Supplies the mode of the open.
+// FileId Supplies the file table entry index
+//
+// RETURN: ESUCCESS is returned if the open operation is successful.
+// ENOENT the named device or file does not exist.
+//
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+// ----------------------------------------------------------------------------
+//
+
+ARC_STATUS
+OmfFileOpen
+ (
+ IN PCHAR OpenPath,
+ IN OPEN_MODE OpenMode,
+ IN OUT PULONG FileId
+ )
+{
+ //
+ // initialize local variables
+ //
+
+ ARC_STATUS Status; // ARC status
+ ULONG DeviceId; // device table entry index
+ POMF_DIR_ENT POmfDirEnt; // OMF directory entry pointer
+ POMF_HDR POmfHeader; // OMF header pointer
+ LARGE_INTEGER AbsolutePosition; // position
+ ULONG TypeIndex,DirIndex; // general indexes
+ ULONG Count; // # of bytes transferred
+ CHAR OmfFileName[OMF_FILE_NAME_LEN]; // folder name
+ BOOLEAN SearchSucceeded = FALSE; // match flag
+ BOOLEAN IsDirectory = FALSE; // directory flag
+ CHAR OmfType[] = {'A','B','\0'}; // default sequance of search:
+ // relocatable MIPS I object
+ // format binary data format
+ // end of chain
+
+ PRINTDBG("OmfFileOpen\n\r"); // debug support
+
+ //
+ // Initialize some variables
+ //
+
+ DeviceId = BlFileTable[ *FileId ].DeviceId;
+ POmfDirEnt = &BlFileTable[ *FileId ].u.OmfFileContext.OmfDirEnt;
+ POmfHeader = &BlFileTable[ DeviceId ].u.OmfHeaderContext.OmfHeader;
+ AbsolutePosition.HighPart=0; // for seek operations
+
+ //
+ // initialize the file/directory pointer to zero
+ //
+
+ BlFileTable[ *FileId ].Position.LowPart=0;
+ BlFileTable[ *FileId ].Position.HighPart=0;
+
+ //
+ // the first char must be the directory char, otherwise it's an error
+ //
+
+ if ( *OpenPath++ != '\\' );
+
+ //
+ // else check if the open is for the root directory
+ //
+
+ else if ( *OpenPath == '\0' )
+ {
+ POmfDirEnt->FolderName[0]='\0';
+ SearchSucceeded = TRUE;
+ IsDirectory = TRUE;
+ }
+
+ //
+ // else validate OMF file name
+ //
+
+ else if ( !OmfFileNameValidate( OpenPath, OmfFileName, OmfType ));
+
+ //
+ // then search the specified file name
+ //
+
+ else
+ {
+ //
+ // save the omf file name
+ //
+
+ strcpy( BlFileTable[ *FileId ].FileName, OpenPath );
+ BlFileTable[ *FileId ].FileNameLength = strlen( OpenPath );
+
+ //
+ // one loop per file
+ //
+
+ for (TypeIndex = 0; !SearchSucceeded && OmfType[TypeIndex]; TypeIndex++)
+ {
+ //
+ // search the directory for the specified OMF file name
+ //
+
+ for ( DirIndex = 0, AbsolutePosition.LowPart =
+ POmfHeader->FolderDirectoryLink << WORD_2P2;
+
+ DirIndex < POmfHeader->FolderCount && !SearchSucceeded;
+
+ DirIndex++, AbsolutePosition.LowPart += sizeof(OMF_DIR_ENT) )
+ {
+ //
+ // exit if error during seek or read.
+ //
+
+ if ((Status = FwSeek(DeviceId, &AbsolutePosition, SeekAbsolute))
+ ||
+ (Status = FwRead(DeviceId,
+ (PVOID)POmfDirEnt,
+ (ULONG)sizeof(OMF_DIR_ENT),
+ &Count )))
+ {
+ return Status;
+ }
+
+ //
+ // check OMF file name
+ //
+
+ SearchSucceeded = CmpOmfFiles( OmfFileName,
+ OmfType[TypeIndex],
+ (PVOID)POmfDirEnt );
+ }
+ }
+
+ //
+ // if the search has been successful, validate file's header
+ //
+
+ if (SearchSucceeded && !OmfFileValidate( *FileId ))
+ {
+ SearchSucceeded = FALSE;
+ }
+ }
+
+ //
+ // At this point we've cracked the name up to (an maybe including the last
+ // component). We located the last component if the SearchSucceeded flag
+ // is true, otherwise the last component does not exist. If we located
+ // the last component then this is like an open or a supersede, but not a
+ // create.
+ //
+
+ if (SearchSucceeded)
+ {
+ //
+ // Check if the last component is a directory
+ //
+
+ if (IsDirectory)
+ {
+ //
+ // For an existing directory the only valid open mode is
+ // OpenDirectory all other modes return an error
+ //
+
+ switch (OpenMode)
+ {
+
+ case ArcOpenReadOnly:
+ case ArcOpenWriteOnly:
+ case ArcOpenReadWrite:
+ case ArcCreateWriteOnly:
+ case ArcCreateReadWrite:
+ case ArcSupersedeWriteOnly:
+ case ArcSupersedeReadWrite:
+
+ //
+ // if we reach here then the caller got a directory but
+ // didn't want to open a directory
+ //
+
+ return EISDIR;
+
+ case ArcOpenDirectory:
+
+ //
+ // if we reach here then the caller got a directory and
+ // wanted to open a directory.
+ //
+
+ BlFileTable[ *FileId ].Flags.Open = 1;
+ BlFileTable[ *FileId ].Flags.Read = 1;
+
+ return ESUCCESS;
+
+ case ArcCreateDirectory:
+
+ //
+ // if we reach here then the caller got a directory and
+ // wanted to create a new directory
+ //
+
+ return EACCES;
+
+ default:
+
+ //
+ // invalid open mode
+ //
+
+ return EINVAL;
+ }
+ }
+
+ //
+ // If we get there then we have an existing file that is being opened.
+ // We can open existing files only read only.
+ //
+
+ switch (OpenMode)
+ {
+ case ArcOpenReadOnly:
+
+ //
+ // if we reach here then the user got a file and wanted to
+ // open the file read only
+ //
+
+ BlFileTable[ *FileId ].Flags.Open = 1;
+ BlFileTable[ *FileId ].Flags.Read = 1;
+
+ return ESUCCESS;
+
+ case ArcOpenWriteOnly:
+ case ArcOpenReadWrite:
+ case ArcCreateWriteOnly:
+ case ArcCreateReadWrite:
+ case ArcSupersedeWriteOnly:
+ case ArcSupersedeReadWrite:
+
+ //
+ // if we reach here then we are trying to open a read only
+ // device for write.
+ //
+
+ return EROFS;
+
+ case ArcOpenDirectory:
+ case ArcCreateDirectory:
+
+ //
+ // if we reach here then the user got a file and wanted a
+ // directory
+ //
+
+ return ENOTDIR;
+
+ default:
+
+ //
+ // invalid open mode
+ //
+
+ return EINVAL;
+ }
+ }
+
+ //
+ // If we get here the last component does not exist so we are trying to
+ // create either a new file or a directory.
+ //
+
+ switch (OpenMode)
+ {
+ case ArcOpenReadOnly:
+ case ArcOpenWriteOnly:
+ case ArcOpenReadWrite:
+ case ArcOpenDirectory:
+
+ //
+ // if we reach here then the user did not get a file but wanted
+ // a file
+ //
+
+ return ENOENT;
+
+ case ArcCreateWriteOnly:
+ case ArcSupersedeWriteOnly:
+ case ArcCreateReadWrite:
+ case ArcSupersedeReadWrite:
+ case ArcCreateDirectory:
+
+ //
+ // if we get hre the user wants to create something.
+ //
+
+ return EROFS;
+
+ default:
+
+ //
+ // invalid open mode
+ //
+
+ return EINVAL;
+ }
+}
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: OmfFileClose:
+//
+// DESCRIPTION: The routine closes the file table entry specified by file id.
+//
+// ARGUMENTS: FileId Supplies the file table index.
+//
+// RETURN: ESUCCESS is returned if the open operation is successful.
+//
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+// ----------------------------------------------------------------------------
+//
+
+ARC_STATUS
+OmfFileClose
+ (
+ IN ULONG FileId
+ )
+{
+ PRINTDBG("OmfFileClose\n\r");
+
+ //
+ // clear flag and exit
+ //
+
+ BlFileTable[FileId].Flags.Open = 0;
+ return ESUCCESS;
+}
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: OmfFileMount:
+//
+// DESCRIPTION: The routine does nothing and return EBADF.
+//
+// ARGUMENTS: MountPath device path specifier.
+// Operation mount operation (load/unload).
+//
+// RETURN: EBADF invalid operation
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+// ----------------------------------------------------------------------------
+//
+
+ARC_STATUS
+OmfFileMount
+ (
+ IN PCHAR MountPath,
+ IN MOUNT_OPERATION Operation
+ )
+{
+ //
+ // return error : invalid operation.
+ //
+
+ return EBADF;
+}
+
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: OmfFileGetReadStatus
+//
+// DESCRIPTION: This routine implements the GetReadStatus operation for the
+// ARC-EISA firmware OMF file.
+//
+// ARGUMENTS: FileId Supplies a pointer to a variable that specifies
+// the file table entry.
+//
+// RETURN: ESUCCESS return always success.
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+// ----------------------------------------------------------------------------
+//
+
+ARC_STATUS
+OmfFileGetReadStatus
+ (
+ IN ULONG FileId
+ )
+{
+ //
+ // return ok
+ //
+
+ return ESUCCESS;
+}
+
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: OmfFileRead:
+//
+// DESCRIPTION: This routine implements the read operation for the ARC-EISA
+// firmware "OMF" driver.
+//
+// ARGUMENTS: FileId Supplies the file table index.
+// Buffer Supplies a pointer to a buffer where the
+// characters read will be stored.
+// Length Supplies the length of Buffer.
+// Count Return the count of the characters that
+// were read.
+//
+// RETURN: ESUCCESS is returned if the open operation is successful.
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+// ----------------------------------------------------------------------------
+//
+
+ARC_STATUS
+OmfFileRead
+ (
+ IN ULONG FileId,
+ IN PVOID Buffer,
+ IN ULONG Length,
+ OUT PULONG Count
+ )
+{
+
+ //
+ // initialize local variables
+ //
+ ARC_STATUS Status; // ARC status
+ POMF_DIR_ENT POmfDirEnt; // OMF directory entry pointer
+ LARGE_INTEGER AbsolutePosition; // OMF file, logical pointer
+ ULONG OmfFileSize; // OMF file size in bytes
+
+ PRINTDBG("OmfFileRead\n\r");
+
+ //
+ // initialize some variables
+ //
+
+ POmfDirEnt = &BlFileTable[ FileId ].u.OmfFileContext.OmfDirEnt;
+
+ //
+ // if directory entry, exit with error
+ //
+
+ if ( !POmfDirEnt->FolderName[0] )
+ {
+ return EBADF; // check this error code "EGI_Q"
+ }
+
+ //
+ // initialize byte count read to zero
+ //
+
+ *Count=0;
+ OmfFileSize = POmfDirEnt->FolderSize << WORD_2P2;
+
+ //
+ // if length is zero or EOF (end of file), return ESUCCESS.
+ //
+
+ if (!Length || BlFileTable[FileId].Position.LowPart >= OmfFileSize)
+ {
+ return ESUCCESS;
+ }
+
+ //
+ // adjust length if it is too big.
+ //
+
+ Length = MIN( Length, OmfFileSize ); // to prevent the add to overflow
+
+ if ( BlFileTable[ FileId ].Position.LowPart + Length > OmfFileSize )
+ {
+ Length = OmfFileSize - BlFileTable[ FileId ].Position.LowPart;
+ }
+
+ //
+ // find OMF absolute offset from OMF file absolute offset
+ //
+
+ AbsolutePosition.HighPart = 0;
+ AbsolutePosition.LowPart = BlFileTable[ FileId ].Position.LowPart +
+ ( POmfDirEnt->FolderLink << WORD_2P2 );
+
+ //
+ // seek + read command
+ //
+
+ if ( (Status = FwSeek( BlFileTable[ FileId ].DeviceId,
+ &AbsolutePosition,
+ SeekAbsolute ))
+ ||
+ (Status = FwRead( BlFileTable[FileId].DeviceId,
+ Buffer,
+ Length,
+ Count )) )
+ {
+ return Status;
+ }
+
+ //
+ // update file pointer and exit
+ //
+
+ BlFileTable[FileId].Position.LowPart += *Count;
+ return ESUCCESS;
+}
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: OmfFileWrite:
+//
+// DESCRIPTION: This routine implements the write operation for the ARC-EISA
+// firmware "OMF" driver.
+//
+// ARGUMENTS: FileId Supplies the file table index.
+// Buffer Supplies a pointer to a buffer where the
+// characters are read.
+// Length Supplies the length of Buffer.
+// Count Return the count of the characters that
+// were written.
+//
+// RETURN: EBADF invalid operation
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+// ----------------------------------------------------------------------------
+//
+
+ARC_STATUS
+OmfFileWrite
+ (
+ IN ULONG FileId,
+ IN PVOID Buffer,
+ IN ULONG Length,
+ OUT PULONG Count
+ )
+{
+ //
+ // return error : invalid operation
+ //
+
+ return EBADF;
+}
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: OmfFileSeek:
+//
+// DESCRIPTION: This routine implements the Seek operation for the
+// ARC-EISA firmware "OMF" driver.
+//
+// ARGUMENTS: FileId Supplies the file table index.
+// Offset Supplies the offset in the file to position to.
+// SeekMode Supplies the mode of the seek operation
+//
+// RETURN: ESUCCESS returned if the operation is successful.
+// EINVAL returned otherwise.
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+// ----------------------------------------------------------------------------
+//
+
+ARC_STATUS
+OmfFileSeek
+ (
+ IN ULONG FileId,
+ IN PLARGE_INTEGER Offset,
+ IN SEEK_MODE SeekMode
+ )
+{
+ //
+ // local variables
+ //
+
+ LARGE_INTEGER Point; // New position
+ POMF_DIR_ENT POmfDirEnt; // OMF directory entry pointer
+
+ PRINTDBG("OmfFileSeek\n\r");
+
+ //
+ // initialize some variables
+ //
+
+ POmfDirEnt = &BlFileTable[ FileId ].u.OmfFileContext.OmfDirEnt;
+
+ //
+ // The offset parameter must be zero, if directory entry.
+ //
+
+ if ( !POmfDirEnt->FolderName[0] && ( Offset->LowPart || Offset->HighPart ))
+ {
+ return EINVAL;
+ }
+
+ //
+ // compute new offset value
+ //
+
+ switch(SeekMode)
+ {
+ case SeekAbsolute:
+ Point = *Offset;
+ break;
+ case SeekRelative:
+ Point = RtlLargeIntegerAdd( BlFileTable[FileId].Position, *Offset );
+ break;
+ default:
+ return EINVAL;
+ }
+
+ //
+ // if new offset is valid, update position field.
+ // if the position value 0-based is equal to the OMF size (1-based),
+ // the EOF has been reached. no error is returned in this case and
+ // the count field is set to zero with ESUCCESS error code for any
+ // successive read operation. note that this combination (ESUCCESS and
+ // count=0) is used to rappresent EOF (end of file).
+ //
+
+ if ( POmfDirEnt->FolderName[0] &&
+ (Point.HighPart || Point.LowPart > POmfDirEnt->FolderSize << WORD_2P2))
+ {
+ return EINVAL;
+ }
+ else
+ {
+ BlFileTable[ FileId ].Position = Point;
+ return ESUCCESS;
+ }
+}
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: OmfFileGetFileInformation:
+//
+// DESCRIPTION: This routine implements the GetFileInformation for the
+// ARC-EISA firmware "OMF" driver.
+//
+// ARGUMENTS: FileId Supplies the file table index.
+// Buffer Supplies the buffer to receive the file
+// information. Note that it must be large
+// enough to hold the full file name.
+//
+// RETURN: EBADF invalid operation
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+// ----------------------------------------------------------------------------
+//
+
+ARC_STATUS
+OmfFileGetFileInformation
+ (
+ IN ULONG FileId,
+ OUT PFILE_INFORMATION Buffer
+ )
+{
+ //
+ // define local variable
+ //
+
+ PBL_FILE_TABLE FileTableEntry = &BlFileTable[ FileId ];
+
+ PRINTDBG("OmfFileGetFileInformation\n\r");
+
+ //
+ // if root, exit with error
+ //
+
+ if ( !FileTableEntry->u.OmfFileContext.OmfDirEnt.FolderName[0] )
+ {
+ return EBADF;
+ }
+
+ //
+ // set output fields
+ //
+
+ RtlZeroMemory(Buffer, sizeof(FILE_INFORMATION));
+
+ //
+ // ending address (high part is already zero) and current address
+ //
+
+ Buffer->EndingAddress.LowPart =
+ FileTableEntry->u.OmfFileContext.OmfDirEnt.FolderSize << WORD_2P2;
+ Buffer->CurrentPosition.LowPart = FileTableEntry->Position.LowPart;
+ Buffer->CurrentPosition.HighPart = FileTableEntry->Position.HighPart;
+
+ //
+ // device type
+ //
+
+ Buffer->Type = OtherPeripheral;
+
+ //
+ // file name length, attributes and file name string
+ //
+
+ Buffer->FileNameLength = FileTableEntry->FileNameLength;
+ Buffer->Attributes = ArcReadOnlyFile;
+ strcpy( Buffer->FileName, FileTableEntry->FileName );
+
+ //
+ // all done
+ //
+
+ return ESUCCESS;
+}
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: OmfFileSetFileInformation:
+//
+// DESCRIPTION: This routine implements the SetFileInformation for the
+// ARC-EISA firmware "OMF" driver.
+//
+// ARGUMENTS: FileId Supplies the file table index.
+// AttributeFlags Supplies the value (on or off) for each
+// attribute being modified.
+// AttributeMask Supplies a mask of the attributes being altered.
+// All other file attributes are left alone.
+//
+// RETURN: EBADF invalid operation
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+// ----------------------------------------------------------------------------
+//
+
+ARC_STATUS
+OmfFileSetFileInformation
+ (
+ IN ULONG FileId,
+ IN ULONG AttributeFlags,
+ IN ULONG AttributeMask
+ )
+{
+ //
+ // return error : invalid operation
+ //
+
+ return EROFS;
+}
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: OmfFileGetDirectoryEntry:
+//
+// DESCRIPTION: This routine implements the GetDirectoryEntry for the
+// ARC-EISA firmware "OMF" driver.
+//
+// ARGUMENTS: FileId Supplies the file table index.
+// DirEntry Pointer to a directory entry structure
+// NumberDir # of entries to read
+// Count # of entries read
+//
+// RETURN: ESUCCESS returned if the operation is successful.
+// EINVAL returned otherwise.
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+// ----------------------------------------------------------------------------
+//
+
+ARC_STATUS
+OmfFileGetDirectoryEntry
+ (
+ IN ULONG FileId,
+ IN DIRECTORY_ENTRY *DirEntry,
+ IN ULONG NumberDir,
+ OUT PULONG CountDir
+ )
+{
+ //
+ // initialize local variables
+ //
+
+ ARC_STATUS Status; // ARC status
+ ULONG DeviceId; // file table entry for the device
+ POMF_HDR POmfHeader; // pointer to OMF ROM/FAT file header
+ ULONG CurrentDir; // current directory entry
+ LARGE_INTEGER AbsolutePosition; // OMF file, pointer of logical pointer
+ OMF_DIR_ENT OmfFileBuffer; // buffer for directory entries
+ ULONG Count; // # of bytes read
+
+ PRINTDBG("OmfFileGetDirectoryEntry\n\r");
+
+ //
+ // if not directory entry, exit with error
+ //
+
+ if ( BlFileTable[ FileId ].u.OmfFileContext.OmfDirEnt.FolderName[0] )
+ {
+ return EBADF;
+ }
+
+ //
+ // Initialize the output count to zero
+ //
+
+ *CountDir=0;
+
+ //
+ // if NumberDir is zero, return ESUCCESS.
+ //
+
+ if ( !NumberDir )
+ {
+ return ESUCCESS;
+ }
+
+ //
+ // initialize variables
+ //
+
+ Count=0;
+ DeviceId = BlFileTable[ FileId ].DeviceId;
+ POmfHeader = &BlFileTable[ DeviceId ].u.OmfHeaderContext.OmfHeader;
+ CurrentDir = BlFileTable[ FileId ].Position.LowPart/sizeof(OMF_DIR_ENT);
+
+ //
+ // if no more entries, return ENOTDIR
+ //
+
+ if ( CurrentDir >= POmfHeader->FolderCount )
+ {
+ return ENOTDIR;
+ }
+
+ //
+ // adjust count if it is too big.
+ //
+
+ NumberDir = MIN( NumberDir, POmfHeader->FolderCount ); //avoid add overflow
+
+ if ( CurrentDir + NumberDir > POmfHeader->FolderCount )
+ {
+ NumberDir = POmfHeader->FolderCount - CurrentDir;
+ }
+
+ //
+ // find OMF absolute offset from OMF file absolute offset
+ //
+
+ AbsolutePosition.HighPart = 0;
+ AbsolutePosition.LowPart = BlFileTable[FileId].Position.LowPart +
+ (POmfHeader->FolderDirectoryLink<<WORD_2P2);
+
+ //
+ // seek command
+ //
+
+ if ( Status = FwSeek( DeviceId, &AbsolutePosition, SeekAbsolute ))
+ {
+ return Status;
+ }
+
+ //
+ // read command
+ //
+
+ while( NumberDir-- )
+ {
+ //
+ // read one directory entry
+ //
+
+ if ( Status = FwRead( DeviceId,
+ &OmfFileBuffer,
+ (ULONG)sizeof(OMF_DIR_ENT),
+ &Count ))
+ {
+ return Status;
+ }
+
+ //
+ // if bytes read are not sizeof(OMF_DIR_ENT), return error
+ //
+
+ if ( Count != sizeof(OMF_DIR_ENT) )
+ {
+ return EBADF;
+ }
+
+ //
+ // convert OMF directory entry in ARC directory entry
+ //
+
+ ConvertOmfDirToArcDir( &OmfFileBuffer, DirEntry++ );
+ ++*CountDir;
+ }
+
+ //
+ // update file pointer and exit
+ //
+
+ BlFileTable[FileId].Position.LowPart += *CountDir * sizeof(OMF_DIR_ENT);
+ return ESUCCESS;
+}
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: MaxOmfFatFiles:
+//
+// DESCRIPTION: The routine returns the most updated file name for the
+// specified product Id.
+// A FALSE is returned if the OMF FAT file name has not been
+// modified.
+//
+// ARGUMENTS: MasterName name used as base
+// CheckedName name checked
+//
+// RETURN: TRUE is returned if the OMF FAT file name has been
+// modified.
+// FALSE is returned in all the other cases.
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+// ----------------------------------------------------------------------------
+//
+
+BOOLEAN
+MaxOmfFatFiles
+ (
+ IN OUT PCHAR MasterName,
+ IN PCHAR CheckedName
+ )
+{
+ //
+ // Define variables
+ //
+
+ CHAR MasterVersion, MasterRevision; // master name
+ CHAR CheckedVersion, CheckedRevision; // checked name
+ POMF_FAT_FILE_NAME PointerMaster; // master name pointer
+ POMF_FAT_FILE_NAME PointerChecked; // checked name pointer
+
+ PRINTDBG("MaxOmfFatFiles\n\r");
+
+ //
+ // save version and revision master values
+ //
+
+ PointerMaster = (POMF_FAT_FILE_NAME)MasterName;
+ MasterVersion = PointerMaster->Version;
+ MasterRevision = PointerMaster->Revision;
+
+ //
+ // save version and revision checked values
+ //
+
+ PointerChecked = (POMF_FAT_FILE_NAME)CheckedName;
+ CheckedVersion = PointerChecked->Version;
+ CheckedRevision = PointerChecked->Revision;
+ PointerChecked->Version = MasterVersion;
+ PointerChecked->Revision = MasterRevision;
+
+ //
+ // update name if new version for the same product Id
+ //
+
+ if (strcmp(MasterName, CheckedName)
+ ||
+ CheckedVersion<MasterVersion
+ ||
+ (CheckedVersion == MasterVersion && CheckedRevision <= MasterRevision))
+ {
+ return FALSE;
+ }
+ else
+ {
+ PointerMaster->Version = CheckedVersion;
+ PointerMaster->Revision = CheckedRevision;
+ return TRUE;
+ }
+}
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: OmfFileNameValidate:
+//
+// DESCRIPTION: The routine validates the requested OMF file name.
+// The name is decomposed in Folder Name and Folder Type.
+//
+// ARGUMENTS: OpenPath Supplies a pointer to a zero terminated OMF
+// file name.
+// OmfFileName Supplies a pointer to an array used to store
+// the Folder Name.
+// OmfType Supplies a pointer to an array used to store
+// the Folder Types.
+//
+// RETURN: TRUE is returned if the operation succeed.
+// FALSE is returned if the OpenPath is incorrect.
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+// ----------------------------------------------------------------------------
+//
+
+BOOLEAN
+OmfFileNameValidate
+ (
+ IN PCHAR OpenPath,
+ OUT PCHAR OmfFileName,
+ OUT PCHAR OmfType
+ )
+
+{
+ //
+ // Define variables
+ //
+
+ ULONG NameIndex; // general index
+
+ PRINTDBG("OmfFileNameValidate\n\r");
+
+ //
+ // name validation
+ //
+
+ for ( NameIndex = 0;
+ NameIndex < OMF_FILE_NAME_LEN && *OpenPath && *OpenPath != '.';
+ NameIndex++ )
+ {
+ if (
+ isupper( *OpenPath ) // upper case letter
+ ||
+ isdigit( *OpenPath ) // digit
+ ||
+ *OpenPath=='-' // '-' minus
+ ||
+ (*OpenPath=='$' && NameIndex==0) // $ char in 1st position
+ )
+ {
+ *OmfFileName++=*OpenPath++;
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+
+ //
+ // return error if name length > of OMF_FILE_NAME_LEN
+ //
+
+ if ( NameIndex == OMF_FILE_NAME_LEN && *OpenPath && *OpenPath != '.')
+ {
+ return FALSE;
+ }
+
+ //
+ // fill right with null chars ('\0') if Folder Name is less than 12 chars
+ //
+
+ while( NameIndex++ < OMF_FILE_NAME_LEN )
+ {
+ *OmfFileName++='\0';
+ }
+
+ //
+ // extension validation
+ //
+
+ if ( *OpenPath++ && *OpenPath ) // skip "null", ".null"
+ {
+ switch( *OpenPath ) // check type field
+ {
+ case 'A':
+ case 'B':
+ *OmfType++ = *OpenPath++;
+ *OmfType = '\0'; // means : end of types
+ break;
+ default:
+ return FALSE;
+ }
+ if( *OpenPath ) // error if more chars
+ {
+ return FALSE;
+ }
+ }
+
+ //
+ // all done, return ok
+ //
+
+ return TRUE;
+}
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: CmpOmfFiles:
+//
+// DESCRIPTION: The routine checks if the selected directory entry has the
+// requested OMF file name.
+//
+// ARGUMENTS: OmfFileName Requested OMF file name pointer.
+// OmfType Requested OMF file type pointer.
+// POmfDirEnt Directory entry to check.
+//
+// RETURN: TRUE is returned if the operation succeed.
+// FALSE is returned if the name or type doesn't match.
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+// ----------------------------------------------------------------------------
+//
+
+BOOLEAN
+CmpOmfFiles
+ (
+ IN PCHAR OmfFileName,
+ IN CHAR OmfType,
+ IN POMF_DIR_ENT POmfDirEnt
+ )
+{
+ //
+ // Define variables
+ //
+
+ ULONG NameIndex; // general index
+
+ PRINTDBG("CmpOmfFiles\n\r");
+
+ //
+ // check name
+ //
+
+ for ( NameIndex=0; NameIndex < OMF_FILE_NAME_LEN; NameIndex++ )
+ {
+ if ( OmfFileName[ NameIndex ] != POmfDirEnt->FolderName[ NameIndex ] )
+ {
+ return FALSE;
+ }
+ }
+
+ //
+ // check extension
+ //
+
+ if ( OmfType != POmfDirEnt->FolderType )
+ {
+ return FALSE;
+ }
+
+ //
+ // all done, return ok
+ //
+
+ return TRUE;
+}
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: OmfHeaderValidate:
+//
+// DESCRIPTION: The routine checks if the specified OMF header data is valid.
+//
+// ARGUMENTS: FileId file table entry index
+//
+// RETURN: TRUE is returned if file is ok.
+// FALSE is returned if file is not correct.
+//
+// ASSUMPTIONS: The header data has already been copied in the
+// context data of the file table entry.
+// The size of all the OMF structures is a multiple of a word.
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+// ----------------------------------------------------------------------------
+//
+
+BOOLEAN
+OmfHeaderValidate
+ (
+ IN ULONG FileId
+ )
+{
+ //
+ // local variables
+ //
+
+ POMF_HDR POmfHeader; // pointer to the header data
+ ULONG OmfDirLink; // directory link in words
+ ULONG OmfDirLength; // directory size in words
+ ULONG OmfSize; // OMF size in bytes
+ UCHAR Checksum=0; // used to compute the checksum
+
+ PRINTDBG("OmfHeaderValidate\n\r");
+
+ //
+ // initialize variables
+ //
+
+ POmfHeader = &BlFileTable[FileId].u.OmfHeaderContext.OmfHeader;
+ OmfDirLink = POmfHeader->FolderDirectoryLink;
+
+ OmfDirLength =(POmfHeader->FolderCount * sizeof(OMF_DIR_ENT))/(1<<WORD_2P2);
+ OmfSize = (ULONG)POmfHeader->FwSize * OMF_BLOCK_SIZE;
+ if (!OmfSize)
+ {
+ OmfSize = OMF_MAX_SIZE;
+ }
+
+ //
+ // check header values
+ //
+
+ if ( POmfHeader->ID[0] != OMF_ID_1ST
+ ||
+ POmfHeader->ID[1] != OMF_ID_2ND
+ ||
+ POmfHeader->ID[2] != OMF_ID_3RD
+ ||
+ POmfHeader->ID[3] != OMF_ID_4TH
+ ||
+ !isalnum(POmfHeader->FwVersion)
+ ||
+ !isalnum(POmfHeader->FwRevision)
+ ||
+ sizeof(OMF_HDR) > OmfSize
+ ||
+ OmfDirLink + OmfDirLength > OmfSize/(1<<WORD_2P2)
+ ||
+ FwFileIdChecksum( FileId,
+ RtlConvertUlongToLargeInteger(0l),
+ (ULONG)(sizeof(OMF_HDR)),
+ &Checksum )
+ ||
+ FwFileIdChecksum( FileId,
+ RtlConvertUlongToLargeInteger(OmfDirLink<<WORD_2P2),
+ OmfDirLength << WORD_2P2,
+ &Checksum )
+// >>> FIXME <<<
+// ||
+// Checksum
+ )
+ {
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
+}
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: OmfFileValidate:
+//
+// DESCRIPTION: The routine checks if the selected file is valid.
+//
+// ARGUMENTS: FileId file table entry index
+//
+// RETURN: TRUE is returned if file is ok.
+// FALSE is returned if file is not correct.
+//
+// ASSUMPTIONS: the folder name and its extension (type) have already
+// been validated.
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+// ----------------------------------------------------------------------------
+//
+
+BOOLEAN
+OmfFileValidate
+ (
+ IN ULONG FileId
+ )
+{
+ //
+ // local variables
+ //
+
+ POMF_DIR_ENT POmfDirEnt; // OMF directory entry pointer
+ ULONG OmfFileLength; // file length, word count
+ ULONG OmfFileLink; // file link, word count
+ ULONG DeviceId; // device id file table entry
+ ULONG OmfLength; // OMF rom length, word count
+ UCHAR Checksum=0; // used to compute the checksum
+
+ PRINTDBG("OmfFileValidate\n\r");
+
+ //
+ // initialize variables
+ //
+
+ POmfDirEnt = &BlFileTable[FileId].u.OmfFileContext.OmfDirEnt;
+ OmfFileLink = POmfDirEnt->FolderLink;
+ OmfFileLength = POmfDirEnt->FolderSize;
+ DeviceId = BlFileTable[FileId].DeviceId;
+ OmfLength=(ULONG)BlFileTable[DeviceId].u.OmfHeaderContext.OmfHeader.FwSize *
+ OMF_BLOCK_SIZE/(1<<WORD_2P2);
+ if (!OmfLength)
+ {
+ OmfLength = OMF_MAX_SIZE/(1<<WORD_2P2);
+ }
+
+ //
+ // validate file
+ //
+
+ if ( OmfFileLink > OMF_MAX_FILE_LINK
+ ||
+ OmfFileLength > OMF_MAX_FILE_LEN
+ ||
+ OmfFileLink + OmfFileLength > OmfLength
+ ||
+ FwFileIdChecksum( DeviceId,
+ RtlConvertUlongToLargeInteger(OmfFileLink<<WORD_2P2),
+ OmfFileLength << WORD_2P2,
+ &Checksum )
+// >>> FIXME <<<
+// ||
+// (Checksum += POmfDirEnt->FolderChecksumByte)
+ )
+ {
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
+}
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: ConvertOmfDirToArcDir:
+//
+// DESCRIPTION: The routine converts the OMF directory entry in the ARC
+// directory entry format.
+//
+// ARGUMENTS: OmfFileBuffer pointer to OMF directory entry
+// DirEntry pointer to ARC directory entry to be filled
+//
+// RETURN: NONE
+//
+// ASSUMPTIONS: FileNameLengthMax is at least 3 chars.
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+// ----------------------------------------------------------------------------
+//
+
+VOID
+ConvertOmfDirToArcDir
+ (
+ IN POMF_DIR_ENT POmfDirEnt,
+ OUT DIRECTORY_ENTRY *PArcDirEnt
+ )
+{
+ //
+ // local variables
+ //
+
+ ULONG CharIndex; // name+extension length
+ ULONG MaxFileName; // max name length
+
+ PRINTDBG("ConvertOmfDirToArcDir\n\r");
+
+ //
+ // set attribute bit (read only file)
+ //
+
+ PArcDirEnt->FileAttribute = ArcReadOnlyFile;
+
+ //
+ // set file name (note that 3 means: '.' + extension + '\0' )
+ //
+
+ MaxFileName = MIN( 32 - 3, OMF_FILE_NAME_LEN );
+
+ for ( CharIndex = 0;
+ CharIndex < MaxFileName && POmfDirEnt->FolderName[ CharIndex ];
+ CharIndex++ )
+ {
+ PArcDirEnt->FileName[ CharIndex ] = POmfDirEnt->FolderName[ CharIndex];
+ }
+
+ //
+ // dot '.'
+ //
+
+ PArcDirEnt->FileName[ CharIndex++ ] = '.';
+
+ //
+ // extension
+ //
+
+ PArcDirEnt->FileName[ CharIndex++ ] = POmfDirEnt->FolderType;
+
+ //
+ // null char
+ //
+
+ PArcDirEnt->FileName[ CharIndex ]='\0';
+
+ //
+ // set length (note: CharIndex is 0-based)
+ //
+
+ PArcDirEnt->FileNameLength = CharIndex;
+
+ //
+ // all done, exit.
+ //
+
+ return;
+}
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: FwGetEisaId:
+//
+// DESCRIPTION: The routine returns the requested board and info id.
+//
+// ARGUMENTS: PathName Option board path name pointer
+// EisaId Pointer to 7 bytes space for the id
+// IdInfo Pointer to 1 byte space for the info id
+//
+// RETURN: TRUE all done.
+// FALSE for any error.
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+// ----------------------------------------------------------------------------
+//
+
+BOOLEAN
+FwGetEisaId
+ (
+ IN PCHAR PathName,
+ OUT PCHAR EisaId,
+ OUT PUCHAR IdInfo
+ )
+{
+ //
+ // define local variables
+ //
+
+ PCONFIGURATION_COMPONENT pComp; // Pointer to a component struc
+ EISA_SLOT_INFO SlotInfo; // pointer to first eisa info
+ BOOLEAN GetIdStatus = FALSE; // be pessimistic
+
+ PRINTDBG("FwGetEisaId\n\r"); // DEBUG SUPPORT
+
+ //
+ // Check to see if the motherboard component is being accessed. Since
+ // Jensen doesn't have a motherboard id, substitute values.
+ //
+
+ if (strstr(PathName, "eisa(0)other(0)") != NULL) {
+ EisaId[0] = 'J';
+ EisaId[1] = 'e';
+ EisaId[2] = 'n';
+ EisaId[3] = 's';
+ EisaId[4] = 'e';
+ EisaId[5] = 'n';
+ EisaId[6] = '0';
+ *IdInfo = 0;
+ GetIdStatus = TRUE;
+
+ //
+ // get the requested component
+ //
+
+ } else if ( (pComp = FwGetComponent(PathName)) == NULL );
+
+ //
+ // check the configuration data length
+ //
+
+ else if ( pComp->ConfigurationDataLength < EISA_SLOT_MIN_INFO );
+
+ //
+ // get the slot info
+ //
+
+ else if ( FwGetConfigurationDataIndex( (PVOID)&SlotInfo,
+ pComp,
+ CONFIGDATAHEADER_SIZE,
+ EISA_SLOT_INFO_SIZE ));
+
+ //
+ // get the requested info
+ //
+
+ else
+ {
+ FwUncompressEisaId( &SlotInfo.Id1stChar, EisaId );
+ *IdInfo = SlotInfo.IdInfo;
+ GetIdStatus = TRUE;
+ }
+
+ //
+ // return status
+ //
+
+ return GetIdStatus;
+}
+
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: FwUncompressEisaId:
+//
+// DESCRIPTION: The routine converts the specified compressed ID in 7 ASCII
+// chars.
+//
+// ARGUMENTS: CompEisaId Pointer to the compressed ID (4 bytes)
+// UncompEisaId Pointer to the uncompressed ID (7 bytes)
+//
+// RETURN: none
+//
+// ASSUMPTIONS: Compressed ID : 1st byte bit 7 - Reserved
+// bits 6-2 - 1st char name comp
+// bits 1-0 - 2nd char name comp
+// 2nd byte bits 7-5 - 2nd char name
+// bits 4-0 - 3rd char name comp
+// 3rd byte bits 7-4 - 1st decimal number comp
+// bits 3-0 - 2nd decimal number comp
+// 4th byte bits 7-4 - 3rd decimal number comp
+// bits 3-0 - 4th decimal number comp
+//
+// Uncompressed ID: 1st byte 1st char name
+// 2nd byte 2nd char name
+// 3rd byte 3rd char name
+// 4th byte 1st decimal number
+// 5th byte 2nd decimal number
+// 6th byte 3rd decimal number
+// 7th byte 4th decimal number
+//
+// Compressed -> Uncompressed :
+//
+// char comp + 'A' - 1 = char uncompressed
+// decimal comp + '0' = decimal uncompressed
+//
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+// ----------------------------------------------------------------------------
+//
+
+VOID
+FwUncompressEisaId
+ (
+ IN PUCHAR CompEisaId,
+ OUT PUCHAR UncompEisaId
+ )
+{
+ //
+ // local variables
+ //
+
+ ULONG Id; // used to hold the 4 bytes ID
+ SHORT i; // general index
+ UCHAR d; // hexadecimal digit
+
+ PRINTDBG("FwUncompressEisaId\n\r");
+
+ //
+ // transform the 4 chars ID in a ULONG
+ //
+
+ Id = Fw4UcharToUlongMSB( CompEisaId );
+
+ //
+ // uncompress 4 digits, starting from the last one
+ //
+
+ for (i=3; i>=0; i--)
+ {
+ d = Id & ID_DIGIT_MASK;
+ UncompEisaId[3+i] = (d <= 9) ? (d + '0') : (d - 0xA + 'A');
+ Id >>= ID_DIGIT_SIZE;
+ }
+
+ //
+ // uncompress 3 chars
+ //
+
+ for (i=2; i>=0; i--)
+ {
+ UncompEisaId[i] = (Id & ID_CHAR_MASK) + 'A' - 1;
+ Id >>= ID_CHAR_SIZE;
+ }
+
+ //
+ // exit
+ //
+
+ return;
+}
+
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: FwGetEisaBusIoCpuAddress:
+//
+// DESCRIPTION: The routine returns the virtual (CPU) address for the specified
+// EISA bus.
+//
+// ARGUMENTS: EisaPath pointer to the path string
+// IoBusAddress pointer to a PVOID variable. It used to store
+// the computed address.
+//
+// RETURN: TRUE returned if all correct.
+// FALSE returned for any error.
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+// ----------------------------------------------------------------------------
+//
+
+BOOLEAN
+FwGetEisaBusIoCpuAddress
+ (
+ IN PCHAR EisaPath,
+ OUT PVOID *IoBusAddress
+ )
+{
+ //
+ // define local variables
+ //
+
+ PCONFIGURATION_COMPONENT PComponent;
+ EISA_ADAPTER_DETAILS EisaInfo;
+
+ PRINTDBG("FwGetEisaBusIoCpuAddress\n\r");
+
+ //
+ // get the requested component and configuration data
+ //
+
+ if ( (PComponent = FwGetComponent( EisaPath )) == NULL ||
+ FwGetConfigurationData( (PVOID)&EisaInfo, PComponent ))
+ {
+ return FALSE;
+ }
+
+ //
+ // Return the requested virtual (CPU) address
+ //
+
+ *IoBusAddress = EisaInfo.IoStart;
+ return TRUE;
+}
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: FwFileChecksum:
+//
+// DESCRIPTION: The routine performs a byte checksum on the specified file.
+//
+// ARGUMENTS: Path File path
+// Checksum File checksum
+//
+// RETURN: ESUCCESS Operation completed successfully.
+// ...other Error code.
+//
+// ASSUMPTIONS: none
+//
+// CALLS: FwFileIdChecksum
+//
+// GLOBALS: none
+//
+// NOTES: The file length must be contained in a ULONG (4G -1).
+// ----------------------------------------------------------------------------
+//
+
+ARC_STATUS
+FwFileChecksum
+ (
+ IN PCHAR Path,
+ OUT PUCHAR Checksum
+ )
+{
+ ARC_STATUS Status;
+ ULONG FileId;
+ FILE_INFORMATION FileInfo;
+
+ //
+ // initialize checksum to zero
+ //
+
+ *Checksum = 0;
+
+ //
+ // open file
+ //
+
+ if (Status = FwOpen( Path, ArcOpenReadOnly, &FileId ))
+ {
+ return Status;
+ }
+
+ //
+ // get file information
+ //
+
+ if (Status = FwGetFileInformation( FileId, &FileInfo ));
+
+ //
+ // return an error if file is greater than 4G - 1
+ //
+
+ else if (FileInfo.EndingAddress.HighPart != 0)
+ {
+ Status = EINVAL;
+ }
+
+ //
+ // perform the checksum and return the status
+ //
+
+ else
+ {
+ Status = FwFileIdChecksum( FileId,
+ FileInfo.StartingAddress,
+ FileInfo.EndingAddress.LowPart,
+ Checksum );
+ }
+
+ //
+ // clase file and return status
+ //
+
+ FwClose( FileId );
+ return Status;
+}
+
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: FwChecksumByte:
+//
+// DESCRIPTION: The routine performs a byte checksum on the specified buffer.
+//
+// ARGUMENTS: Buffer Pointer to area to checksum.
+// Length Length of area to checksum (bytes).
+// ChecksumByte The pointed byte is used in input as a
+// starting checksum value and in output as
+// the final checksum value.
+//
+// RETURN: ESUCCESS operation completed successfully
+//
+// ASSUMPTIONS: none
+//
+// CALLS: none
+//
+// GLOBALS: none
+//
+// NOTES: none
+//
+// ----------------------------------------------------------------------------
+//
+
+ARC_STATUS
+FwChecksumByte (
+ IN PUCHAR Buffer,
+ IN ULONG Length,
+ IN OUT PUCHAR ChecksumByte
+ )
+{
+ //
+ // checksum the buffer and exit
+ //
+
+ while (Length--)
+ {
+ *ChecksumByte += *Buffer++;
+ }
+
+ return ESUCCESS;
+}
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: FwFileIdChecksum:
+//
+// DESCRIPTION: The routine performs a byte checksum within the spcified
+// range of the FileId.
+//
+// ARGUMENTS: FileId File table entry index.
+// StartingOffset Beginning of checksum range (byte offset).
+// Length Number of bytes to checksum.
+// Checksum Input : start checksum value
+// Output: image checksum
+//
+// RETURN: ESUCCESS Operation completed successfully.
+// ...other Error code.
+//
+// ASSUMPTIONS: none
+//
+// CALLS: FwChecksumByte
+//
+// GLOBALS: none
+//
+// NOTES: This routine can also be called during the "open" phase
+// (the open bit is not set), because the read and seek functions
+// are called directly using the table within the file id
+// descriptor.
+// ----------------------------------------------------------------------------
+//
+
+ARC_STATUS
+FwFileIdChecksum
+ (
+ IN ULONG FileId,
+ IN LARGE_INTEGER StartingOffset,
+ IN ULONG Length,
+ IN OUT PUCHAR Checksum
+ )
+{
+ ARC_STATUS Status;
+ ULONG BytesToRead;
+ ULONG Count;
+ UCHAR TempBuffer[MAXIMUM_SECTOR_SIZE + MAX_DCACHE_LINE_SIZE];
+ PUCHAR TempPointer = ALIGN_BUFFER( TempBuffer );
+
+ //
+ // If buffer length is zero, return ESUCCESS
+ //
+
+ if (Length==0)
+ {
+ return ESUCCESS;
+ }
+
+ //
+ // position the file pointer
+ //
+
+ if (Status = (BlFileTable[FileId].DeviceEntryTable->Seek)
+ (FileId, &StartingOffset, SeekAbsolute))
+ {
+ return Status;
+ }
+
+ //
+ // perform the checksum
+ //
+
+ do
+ {
+ BytesToRead = MIN( Length, MAXIMUM_SECTOR_SIZE );
+
+ //
+ // fill the buffer
+ //
+
+ if (Status = (BlFileTable[FileId].DeviceEntryTable->Read)
+ (FileId, TempPointer, BytesToRead, &Count))
+ {
+ return Status;
+ }
+
+ //
+ // make sure that we got the requested number of bytes
+ //
+
+ if (Count != BytesToRead)
+ {
+ return EINVAL;
+ }
+
+ //
+ // checksum the area
+ //
+
+ FwChecksumByte( TempPointer, BytesToRead, Checksum);
+
+ } while ( Length -= BytesToRead );
+
+ //
+ // all done
+ //
+
+ return Status;
+}
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: FwGetMnemonicKey;
+//
+// DESCRIPTION: The routine returns the specified key. The specified key
+// within the path string must be in digits, an error is returned
+// otherwise.
+//
+// ARGUMENTS: Path pointer to the pathname string
+// Mnemonic mnemonic string
+// Key pointer to buffer used to hold the ouput
+//
+// RETURN: TRUE returned if all correct
+// FALSE returned invalid input parameter
+//
+// ASSUMPTIONS:
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+// ----------------------------------------------------------------------------
+//
+
+BOOLEAN
+FwGetMnemonicKey
+ (
+ IN PCHAR Path,
+ IN PCHAR Mnemonic,
+ IN PULONG Key
+ )
+{
+ PCHAR Tmp;
+ PCHAR Tmp2;
+ CHAR Digits[ KEY_MAX_DIGITS + 1 ];
+ ULONG i;
+ CHAR String[ MAX_MNEMONIC_LEN + 3 ]; // mnemonic + ')' + '(' + '\0'
+
+ PRINTDBG("FwGetMnemonicKey\n\r");
+
+ //
+ // Construct a string of the form ")mnemonic("
+ //
+
+ String[0]=')';
+ for(i=1; *Mnemonic; i++)
+ {
+ String[i] = * Mnemonic++;
+ }
+ String[i++]='(';
+ String[i]='\0';
+
+ //
+ // first look for the "mnemonic(" string.
+ //
+
+ if ( (Tmp = strstr( Path, &String[1] )) == NULL)
+ {
+ return FALSE;
+ }
+
+ //
+ // if not the begin of the path name, look for the ")mnemonic(" string.
+ //
+
+ if (Tmp != Path)
+ {
+ if ( (Tmp = strstr( Path, String )) == NULL)
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ i--;
+ }
+
+ //
+ // skip the mnemonic
+ //
+
+ Tmp+=i;
+
+ //
+ // make sure that the number of digits is within the allowed range
+ //
+
+ if ((Tmp2 = strchr(Tmp, ')')) == NULL || Tmp2 - Tmp > KEY_MAX_DIGITS )
+ {
+ return FALSE;
+ }
+
+ //
+ // convert the value in between parentesis to integer
+ //
+
+ for ( i=0; *Tmp != ')'; i++ )
+ {
+ if ( !isdigit( Digits[i] = *Tmp++ ))
+ {
+ return FALSE;
+ }
+ }
+ Digits[i]='\0';
+
+ //
+ // return the converted number
+ //
+
+ *Key = i ? atoi(Digits) : 0;
+ return TRUE;
+}
+
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: FwGetNextMnemonic:
+//
+// DESCRIPTION: The routine returns the next mnemonic in the list.
+// If Mnemonic is a null string, the first mnemonic of the list
+// is returned. The FALSE value is returned if the specified
+// mnemonic is not present or end of list.
+//
+//
+// ARGUMENTS: Path pointer to the pathname string.
+// Mnemonic mnemonic string pointer
+// NextMnemonic next mnemonic string pointer
+//
+// RETURN: TRUE returned if all correct
+// FALSE returned if invalid input parameter or end of
+// list
+//
+// ASSUMPTIONS: The path is composed by ARC mnemonic names as follows:
+// adapter(.)..adapter(.)controller(.)peripheral(.)'\0'.
+// The NextMnemonic string is big enough to hold the mnemonic
+// name.
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+// ----------------------------------------------------------------------------
+//
+
+BOOLEAN
+FwGetNextMnemonic
+ (
+ IN PCHAR Path,
+ IN PCHAR Mnemonic,
+ OUT PCHAR NextMnemonic
+ )
+{
+ //
+ // local variables
+ //
+
+ PCHAR Tmp = Path;
+ PCHAR Tmp2;
+ ULONG i;
+ CHAR String[ MAX_MNEMONIC_LEN + 3 ]; // mnemonic + ')' + '(' + '\0'
+
+ PRINTDBG("FwGetNextMnemonic\n\r");
+
+ if ( *Mnemonic )
+ {
+ //
+ // Construct a string of the form ")mnemonic("
+ //
+
+ String[0]=')';
+ for(i=1; *Mnemonic; i++)
+ {
+ String[i] = *Mnemonic++;
+ }
+ String[i++]='(';
+ String[i]='\0';
+
+ //
+ // first look for the "mnemonic(" string.
+ //
+
+ if ( (Tmp = strstr( Path, &String[1] )) == NULL)
+ {
+ return FALSE;
+ }
+
+ //
+ // if not the begin of the path name, look for the ")mnemonic(" string.
+ //
+
+ if (Tmp != Path)
+ {
+ if ( (Tmp = strstr( Path, String )) == NULL)
+ {
+ return FALSE;
+ }
+ Tmp++;
+ }
+
+ //
+ // return an error if there is another mnemonic with same name
+ //
+
+ if (strstr( Tmp, String ) != NULL)
+ {
+ return FALSE;
+ }
+
+ //
+ // find the start of the next mnemonic
+ //
+
+ if ( (Tmp = strchr(Tmp,')')) == NULL )
+ {
+ return FALSE;
+ }
+ Tmp++;
+ }
+
+ //
+ // find the end of the next mnemonic and copy it.
+ //
+
+ if ( (Tmp2 = strchr(Tmp,'(')) == NULL || Tmp2 == Tmp ||
+ strchr( Tmp2, ')') == NULL )
+ {
+ return FALSE;
+ }
+
+ //
+ // copy the mnemonic
+ //
+
+ while( Tmp < Tmp2 )
+ {
+ *NextMnemonic++ = *Tmp++;
+ }
+ *NextMnemonic = '\0';
+
+ //
+ // return all done
+ //
+
+ return TRUE;
+}
+
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: FwGetMnemonicPath:
+//
+// DESCRIPTION: The routine returns a pointer to the mnemonic path.
+// The routine uses the first mnemoic match to built
+// the mnemonic path.
+//
+// ARGUMENTS: Path pointer to the path string.
+// Mnemonic pointer to the mnemomic.
+// MnemonicPath pointer to the mnemonic path string.
+//
+// RETURN: TRUE returned if all correct.
+// FALSE returned for any error.
+//
+// ASSUMPTIONS: the string pointed by MnemonicPath must be enough large to
+// contain the mnemoinc path.
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+// ----------------------------------------------------------------------------
+//
+
+BOOLEAN
+FwGetMnemonicPath
+ (
+ IN PCHAR Path,
+ IN PCHAR Mnemonic,
+ OUT PCHAR MnemonicPath
+ )
+{
+ //
+ // local variables
+ //
+
+ PCHAR Tmp;
+ ULONG i;
+ CHAR String[ MAX_MNEMONIC_LEN + 3 ]; // mnemonic + ')' + '(' + '\0'
+
+ PRINTDBG("FwGetMnemonicPath\n\r");
+
+ //
+ // Construct a string of the form ")mnemonic("
+ //
+
+ String[0]=')';
+ for(i=1; *Mnemonic; i++)
+ {
+ String[i] = *Mnemonic++;
+ }
+ String[i++]='(';
+ String[i]='\0';
+
+ //
+ // first look for the "mnemonic(" string.
+ //
+
+ if ( (Tmp = strstr( Path, &String[1] )) == NULL)
+ {
+ return FALSE;
+ }
+
+ //
+ // if not the begin of the path name, look for the ")mnemonic(" string.
+ //
+
+ if (Tmp != Path)
+ {
+ if ( (Tmp = strstr( Path, String )) == NULL)
+ {
+ return FALSE;
+ }
+ Tmp++;
+ }
+
+ //
+ // find the end of this mnemonic
+ //
+
+ if ( (Tmp = strchr(Tmp,')')) == NULL )
+ {
+ return FALSE;
+ }
+
+ //
+ // copy the mnemonic path in the output string
+ //
+
+ strncpy( MnemonicPath, Path, Tmp-Path+1 );
+ MnemonicPath[ Tmp-Path+1 ] = '\0';
+
+ //
+ // all done, return
+ //
+
+ return TRUE;
+}
+
+
+
+
+
+// ----------------------------------------------------------------------------
+// PROCEDURE: GetNextPath:
+//
+// DESCRIPTION: The routine isolates the first path string entry form the
+// specified path string list.
+//
+// ARGUMENTS: PathList pointer to the path string list pointer.
+// it is updated upon return to point the
+// next path string entry.
+// PathTarget pointer to the isolated path string.
+//
+//
+// RETURN: TRUE returned if operation is successful.
+// FALSE returned if end of list has been reached.
+//
+// ASSUMPTIONS: The path string list is ended with a null char ('\0') and
+// the path string entries are separated from each other with
+// the ';' char.
+// The target string has enough space to hold the isolated
+// path string.
+//
+// CALLS:
+//
+// GLOBALS:
+//
+// NOTES:
+// ----------------------------------------------------------------------------
+//
+
+BOOLEAN
+GetNextPath
+ (
+ IN OUT PCHAR *PPathList,
+ OUT PCHAR PathTarget
+ )
+{
+ PRINTDBG("GetNextPath\n\r");
+
+ //
+ // if end of list, retrun with error
+ //
+
+ if (!**PPathList)
+ {
+ return FALSE;
+ }
+
+ //
+ // copy the path string and update the pointer
+ //
+
+ for (; *PathTarget=**PPathList; *PathTarget++, *(*PPathList)++)
+ {
+ if (**PPathList==';')
+ {
+ *PathTarget='\0';
+ (*PPathList)++;
+ break;
+ }
+ }
+ return TRUE;
+}
+
+
+
+
diff --git a/private/ntos/fw/alpha/pal/checked/a221064.pal b/private/ntos/fw/alpha/pal/checked/a221064.pal
new file mode 100644
index 000000000..d1fe76200
--- /dev/null
+++ b/private/ntos/fw/alpha/pal/checked/a221064.pal
Binary files differ
diff --git a/private/ntos/fw/alpha/pal/checked/a221066.pal b/private/ntos/fw/alpha/pal/checked/a221066.pal
new file mode 100644
index 000000000..5218fdf82
--- /dev/null
+++ b/private/ntos/fw/alpha/pal/checked/a221066.pal
Binary files differ
diff --git a/private/ntos/fw/alpha/pal/checked/a221164.pal b/private/ntos/fw/alpha/pal/checked/a221164.pal
new file mode 100644
index 000000000..4cd25e971
--- /dev/null
+++ b/private/ntos/fw/alpha/pal/checked/a221164.pal
Binary files differ
diff --git a/private/ntos/fw/alpha/pal/checked/a321064.pal b/private/ntos/fw/alpha/pal/checked/a321064.pal
new file mode 100644
index 000000000..5a1c618ab
--- /dev/null
+++ b/private/ntos/fw/alpha/pal/checked/a321064.pal
Binary files differ
diff --git a/private/ntos/fw/alpha/pal/free/a221064.pal b/private/ntos/fw/alpha/pal/free/a221064.pal
new file mode 100644
index 000000000..ae1f70f57
--- /dev/null
+++ b/private/ntos/fw/alpha/pal/free/a221064.pal
Binary files differ
diff --git a/private/ntos/fw/alpha/pal/free/a221066.pal b/private/ntos/fw/alpha/pal/free/a221066.pal
new file mode 100644
index 000000000..d1578dc6a
--- /dev/null
+++ b/private/ntos/fw/alpha/pal/free/a221066.pal
Binary files differ
diff --git a/private/ntos/fw/alpha/pal/free/a221164.pal b/private/ntos/fw/alpha/pal/free/a221164.pal
new file mode 100644
index 000000000..930f49395
--- /dev/null
+++ b/private/ntos/fw/alpha/pal/free/a221164.pal
Binary files differ
diff --git a/private/ntos/fw/alpha/pal/free/a321064.pal b/private/ntos/fw/alpha/pal/free/a321064.pal
new file mode 100644
index 000000000..d297c83fb
--- /dev/null
+++ b/private/ntos/fw/alpha/pal/free/a321064.pal
Binary files differ
diff --git a/private/ntos/fw/alpha/readme.txt b/private/ntos/fw/alpha/readme.txt
new file mode 100644
index 000000000..c2cf20d06
--- /dev/null
+++ b/private/ntos/fw/alpha/readme.txt
@@ -0,0 +1,11 @@
+This directory contains firmware source files common to all ALPHA platforms.
+
+Be sure to check this directory first before editing source files in any
+platform specific directory. The build procedure copies files from here
+to the platform specific directory, so multiple copies may exist. Files
+that are in this directory are the only maintained copies. If a file exists
+both here and in a platform specific directory, edits must be done here.
+
+Builds for each machine are done in the appropriate subdirectory of fw\alpha.
+E.g.: Builds for Morgan are done in fw\alpha\morgan, and builds for Jensen
+are done in fw\alpha\jensen. Each machine has its own firmware PALcode.
diff --git a/private/ntos/fw/alpha/rom.c b/private/ntos/fw/alpha/rom.c
new file mode 100644
index 000000000..ecd168ab3
--- /dev/null
+++ b/private/ntos/fw/alpha/rom.c
@@ -0,0 +1,1079 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ rom.c
+
+Abstract:
+
+ This module provides support for different kinds of ROMs/PROMs/Flash
+ ROMs in Alpha AXP machines.
+
+ Neither this file or rom.h makes an attempt at universal ROM support.
+
+ Current support set:
+
+ Intel: 28F008SA 1 megabyte Flash Memory
+
+ AMD: Am29F010 128KB Sector Erase Flash Memory
+
+
+Author:
+
+ John DeRosa 4-May-1993
+
+Revision History:
+
+--*/
+
+#include "fwp.h"
+#include "rom.h"
+
+//
+// Function prototypes
+//
+
+ARC_STATUS
+FwErase28F008SA(
+ IN PUCHAR EraseAddress
+ );
+
+
+ARC_STATUS
+FwByteWrite28F008SA(
+ IN PUCHAR WriteAddress,
+ IN UCHAR WriteData
+ );
+
+ARC_STATUS
+FwEraseAM29F010 (
+ IN PUCHAR EraseAddress
+ );
+
+ARC_STATUS
+FwByteWriteAM29F010 (
+ IN PUCHAR WriteAddress,
+ IN UCHAR WriteData
+ );
+
+//
+// ROM identification and control values.
+//
+// These are based on:
+//
+// Am29F010: AMD publication #16736, Rev. C, Amendment/0, September 1992.
+// 28F008SA: Intel order number 290429-003, September 1992.
+//
+// Table notes:
+//
+// Addresses for the ID command and response sequences are absolute,
+// since this code assumes homogeneous ROM arrays. The code will only
+// test the chip at the lowest Jensen ROM address.
+//
+// Offsets for the Reset and Set Read-mode commands are relative to the
+// base address of the individual ROM chip.
+//
+// Addresses passed to the erase-block function are within the block
+// to be erased.
+//
+// Addresses passed to the write-byte function are the address of the byte
+// to be written.
+//
+// The chip block size must be less than or equal to 64KB.
+//
+// N.B. The function that determines the ROM type will test each entry
+// in RomValues, starting at the beginning. This requires issuing write
+// commands to the ROM chip. So care must be taken that the ID command
+// write sequence for ROM type "n" will not have a deliterious effect on
+// other ROM types which may be in the machine, but are not identified until
+// RomValues entry "n + x".
+//
+//
+
+ROM_VALUES RomValues[InvalidROM] = {
+
+ { 15, // Standard stall amount
+ 1, // ID command length
+ 2, // ID response length
+ 1, // Reset command length
+ 1, // Read command length
+ I28F008SA, // ROM being described
+ 0x100000, // 1MB per chip
+ 0x10000, // 64KB per block
+ { {(PUCHAR)PROM_VIRTUAL_BASE, 0x90} }, // ID command sequence
+ { {(PUCHAR)PROM_VIRTUAL_BASE, 0x89}, // ID response sequence
+ {(PUCHAR)PROM_VIRTUAL_BASE+1, 0xa2} },
+ { {0, 0x50} }, // Reset command sequence
+ { {0, 0xff} }, // Read command sequence
+ FwErase28F008SA, // Sector erase function
+ FwByteWrite28F008SA // Byte write function
+ },
+
+ { 15, // Standard stall amount
+ 3, // ID command length
+ 2, // ID response length
+ 3, // Reset command length
+ 3, // Read command length
+ Am29F010, // ROM being described
+ 0x20000, // 128KB per chip
+ 0x4000, // 16KB per block
+ { {(PUCHAR)PROM_VIRTUAL_BASE+0x5555, 0xaa},
+ {(PUCHAR)PROM_VIRTUAL_BASE+0x2aaa, 0x55},
+ {(PUCHAR)PROM_VIRTUAL_BASE+0x5555, 0x90} }, // ID command sequence
+ { {(PUCHAR)PROM_VIRTUAL_BASE, 1}, // ID response sequence
+ {(PUCHAR)PROM_VIRTUAL_BASE+1, 0x20} },
+ { {0x5555, 0xaa},
+ {0x2aaa, 0x55},
+ {0x5555, 0xf0} }, // Reset command sequence
+ { {0x5555, 0xaa},
+ {0x2aaa, 0x55},
+ {0x5555, 0xf0} }, // Read command sequence
+ FwEraseAM29F010, // Sector erase function
+ FwByteWriteAM29F010 // Byte write function
+ }
+};
+
+
+//
+// Miscellaneous notes.
+//
+// A call must first be made to FwROMDetermineMachineROMType. If this
+// returns ESUCCESS, then it has loaded the ROM type into the global variable
+// MachineROMType.
+//
+// After MachineROMType has been loaded, these functions may be called
+// to manipulate the system ROM:
+//
+// FwROMByteWrite
+// FwROMErase64KB
+// FwROMEraseBlock
+// FwROMResetStatus
+// FwROMSetARCDataToReadMode
+// FwROMSetReadMode
+//
+// FwROMErase64KB and FwROMSetARCDataToReadMode work on a "virtual"
+// 64KB ROM block, for compatibility with the first version of Jensen
+// hardware.
+//
+
+//
+// The type of ROM in this machine.
+//
+
+ROM_TYPE MachineROMType;
+
+
+ARC_STATUS
+Check28F008SAStatusAndClear (
+ IN ULONG WhichToCheck
+ )
+/*++
+
+Routine Description:
+
+ This checks the status of an Intel 28F008SA 1MB Flash ROM. The
+ base address of the Jensen space, PROM_VIRTUAL_BASE, is used since
+ we know there is only one of these chips in the machine.
+
+ Hack: The hardwired values here should be changed to come out of
+ the RomValues array.
+
+Arguments:
+
+ WhichToCheck = 0 if a block-erase status check is desired.
+ = 1 if a byte-write status check is desired.
+
+ROM state on exit:
+
+ The status register is cleared.
+
+Return Value:
+
+ Returns ESUCCESS if the status is OK.
+ Otherwise, EIO is returned.
+
+--*/
+
+{
+ UCHAR FooBar;
+
+ //
+ // Check the full status when the PROM's write state machine is ready.
+ //
+
+ while (((FooBar = READ_PORT_UCHAR((PUCHAR)PROM_VIRTUAL_BASE)) &
+ 0x80) == 0 ) {
+ VenStallExecution(15);
+ }
+
+ VenStallExecution(15);
+ FwROMResetStatus((PUCHAR)PROM_VIRTUAL_BASE);
+
+ switch (WhichToCheck) {
+
+ //
+ // block-erase status check
+ //
+
+ case 0:
+
+ if ( ((FooBar & 0x28) != 0) || ((FooBar & 0x30) == 0x30) ) {
+ // Error in erase
+ return EIO;
+ } else {
+ // Erase was successful
+ return ESUCCESS;
+ }
+
+ //
+ // byte-write status check
+ //
+
+ case 1:
+
+ if (FooBar & 0x18) {
+ // Error in write
+ return EIO;
+ } else {
+ // Write was successful
+ return ESUCCESS;
+ }
+
+
+ //
+ // We should never get here.
+ //
+
+ default:
+ return EIO;
+ }
+}
+
+
+ARC_STATUS
+FwErase28F008SA(
+ IN PUCHAR EraseAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This erases a block in an Intel 28F008SA 1MB Flash ROM. The
+ base address of the Jensen space, PROM_VIRTUAL_BASE, is used since
+ we know there is only one of these chips in the machine.
+
+ Hack: The hardwired values here should be changed to come out of
+ the RomValues array.
+
+Arguments:
+
+ EraseAddress - An address within the block to be erased.
+
+ROM state on exit:
+
+ The status register is left in a cleared (reset) state.
+ The ROM is left in read-array mode.
+
+Return Value:
+
+ Returns ESUCCESS if the erase was successful.
+ Otherwise, EIO is returned.
+
+--*/
+
+{
+ ULONG FooBar;
+
+ for (FooBar = 0; FooBar <= 10; FooBar++) {
+
+ FwROMResetStatus((PUCHAR)PROM_VIRTUAL_BASE);
+
+ WRITE_PORT_UCHAR (EraseAddress, 0x20);
+ AlphaInstMB();
+ WRITE_PORT_UCHAR (EraseAddress, 0xd0);
+ AlphaInstMB();
+
+ // Stall 1 second
+ VenStallExecution(1 * 1000 * 1000);
+
+ if (Check28F008SAStatusAndClear(0) == ESUCCESS) {
+ FwROMSetReadMode((PUCHAR)PROM_VIRTUAL_BASE);
+ return ESUCCESS;
+ }
+
+ // In case the device is busy, give it some time to settle.
+ VenStallExecution(3 * 1000 * 1000);
+ }
+
+
+ //
+ // If we get here, we have tried unsuccessfully 10 times to erase
+ // this block. Return an error.
+ //
+
+ FwROMSetReadMode((PUCHAR)PROM_VIRTUAL_BASE);
+ return EIO;
+}
+
+
+ARC_STATUS
+FwByteWrite28F008SA(
+ IN PUCHAR WriteAddress,
+ IN UCHAR WriteData
+ )
+
+/*++
+
+Routine Description:
+
+ This writes a byte in the Alpha/Jensen 1MB PROM. It retries up to
+ 20 times if the write status register indicates failure, or a read
+ of the location indicates that the write was partially done
+ by the device.
+
+ Hack: The hardwired values here should be changed to come out of
+ the RomValues array.
+
+Arguments:
+
+ WriteAddress = meta-virtual address of the byte to be written.
+ WriteData = byte to be written.
+
+ROM state on exit:
+
+ The byte is written, and the WSM status register is modified.
+
+Return Value:
+
+ ESUCCESS if the write was successful.
+ Otherwise, EIO.
+
+--*/
+
+{
+ ULONG Index;
+ UCHAR WSMStatus;
+
+ FwROMResetStatus((PUCHAR)PROM_VIRTUAL_BASE);
+
+ for (Index = 0; Index < 20; Index++) {
+
+ WRITE_PORT_UCHAR (WriteAddress, 0x40);
+ AlphaInstMB();
+ WRITE_PORT_UCHAR (WriteAddress, WriteData);
+ AlphaInstMB();
+
+ //
+ // The device should need only 7 microseconds.
+ //
+
+ VenStallExecution(15);
+
+ if (Check28F008SAStatusAndClear(1) != ESUCCESS) {
+
+ //
+ // The write failed. Ensure status is clear and see if we
+ // can retry.
+ //
+
+ FwROMResetStatus((PUCHAR)PROM_VIRTUAL_BASE);
+ FwROMSetReadMode((PUCHAR)PROM_VIRTUAL_BASE);
+ VenPrint2("? Write failed to address %x. Wrote %x, ",
+ WriteAddress, WriteData);
+ VenPrint1("verify returns %x.\r\n",
+ READ_PORT_UCHAR((PUCHAR)WriteAddress));
+
+ if (READ_PORT_UCHAR(WriteAddress) != 0xff) {
+ VenPrint("RETRY ABORTED!\r\n");
+ return EIO;
+ } else {
+ VenPrint("Retrying..\r\n");
+ }
+
+ } else {
+
+ //
+ // The write succeeded.
+ //
+
+ return ESUCCESS;
+ }
+
+ }
+
+
+ //
+ // We failed to write the byte after 20 tries.
+ //
+
+ return EIO;
+
+}
+
+
+ARC_STATUS
+CheckAM29F010Status (
+ IN BOOLEAN SectorErase,
+ IN PUCHAR Address,
+ IN UCHAR Data
+ )
+/*++
+
+Routine Description:
+
+ This checks the status of an AMD 29F010 128KB ROM chip after a
+ byte write or sector erase command has been issued. Data Polling
+ is used.
+
+Arguments:
+
+ SectorErase - TRUE if a sector erase is under way.
+ FALSE if a byte write is under way.
+
+ Address - The address of the ROM byte that was just
+ written, or an address within the chip that
+ was just given an erase command.
+
+ Data - If a byte write is under way, this is the byte
+ that was written.
+
+ If a sector erase is under way, this must be
+ a value in the range 0xf0 -- 0xff.
+
+ROM state on exit:
+
+ The ROM is left at the end of its sector erase or byte write algorithm.
+
+Return Value:
+
+ Returns ESUCCESS if the status is OK.
+
+ Otherwise, EIO is returned.
+
+--*/
+
+{
+ UCHAR Character;
+ ULONG Retries;
+
+ //
+ // If we are doing an erase command, check whether the erase command
+ // was accepted. This is supposed to happen within the first 100 usec.
+ //
+
+ if (SectorErase) {
+
+ Retries = 0;
+
+ while ((READ_PORT_UCHAR(Address) & 0x08) != 0x08) {
+ Retries++;
+ VenStallExecution(22);
+ if (Retries == 10) {
+ return (EIO);
+ }
+ }
+ }
+
+ //
+ // Do data polling until the device signals success or a timeout.
+ //
+
+ while (TRUE) {
+
+ Character = READ_PORT_UCHAR(Address);
+
+ //
+ // Has the device finished?
+ //
+
+ if (((Character ^ Data) & 0x80) == 0) {
+
+ //
+ // DQ7 says yes!
+ //
+
+ return (ESUCCESS);
+ }
+
+ //
+ // Check for time-out. If a possible time-out condition, DQ7 is
+ // re-read and re-checked to account for the case of simultaneous
+ // updates to DQ5 and DQ7.
+ //
+
+ if (Character & 0x20) {
+
+ if (((READ_PORT_UCHAR(Address) ^ Data) & 0x80) == 0) {
+
+ // DQ7 says success!
+ return (ESUCCESS);
+
+ } else {
+
+ // DQ5 and DQ7 say time-out.
+ return (EIO);
+ }
+ }
+ }
+}
+
+ARC_STATUS
+FwEraseAM29F010 (
+ IN PUCHAR EraseAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This erases a block in an AMD AM29F010 128KB Flash ROM.
+
+Arguments:
+
+ EraseAddress - An address within the block to be erased.
+
+ROM state on exit:
+
+ The status register is left in a cleared (reset) state.
+ The ROM is left in read-array mode.
+
+Return Value:
+
+ Returns ESUCCESS if the erase was successful.
+ Otherwise, EIO is returned.
+
+--*/
+
+{
+ ULONG FooBar;
+ PUCHAR Address;
+
+ //
+ // Concoct the base address of this ROM chip.
+ //
+
+ Address = (PUCHAR)
+ ((ULONG)EraseAddress &
+ ~(RomValues[MachineROMType].BytesPerChip - 1));
+
+ for (FooBar = 0; FooBar <= 10; FooBar++) {
+
+ FwROMResetStatus(EraseAddress);
+
+ WRITE_PORT_UCHAR (Address+0x5555, 0xaa);
+ VenStallExecution(2);
+ WRITE_PORT_UCHAR (Address+0x2aaa, 0x55);
+ VenStallExecution(2);
+ WRITE_PORT_UCHAR (Address+0x5555, 0x80);
+ VenStallExecution(2);
+ WRITE_PORT_UCHAR (Address+0x5555, 0xaa);
+ VenStallExecution(2);
+ WRITE_PORT_UCHAR (Address+0x2aaa, 0x55);
+ VenStallExecution(2);
+ WRITE_PORT_UCHAR (EraseAddress, 0x30);
+
+ if (CheckAM29F010Status(TRUE, EraseAddress, 0xff) == ESUCCESS) {
+ FwROMSetReadMode(EraseAddress);
+ return ESUCCESS;
+ }
+
+ //
+ // We have to retry the erase. Give the device some time to settle.
+ //
+
+ VenStallExecution(1 * 1000 * 1000);
+ }
+
+
+ //
+ // If we get here, we have tried unsuccessfully 10 times to erase
+ // this block. Return an error.
+ //
+
+ FwROMSetReadMode(EraseAddress);
+
+ return EIO;
+}
+
+ARC_STATUS
+FwByteWriteAM29F010 (
+ IN PUCHAR WriteAddress,
+ IN UCHAR WriteData
+ )
+
+/*++
+
+Routine Description:
+
+ This writes a byte in an AMD AM29F010 128KB Flash ROM. It retries up to
+ 20 times if the write status register indicates failure, or a read
+ of the location indicates that the write was partially done
+ by the device.
+
+Arguments:
+
+ WriteAddress = meta-virtual address of the byte to be written.
+ WriteData = byte to be written.
+
+ROM state on exit:
+
+ The byte is written, and the WSM status register is modified.
+
+Return Value:
+
+ ESUCCESS if the write was successful.
+ Otherwise, EIO.
+
+--*/
+
+{
+ ULONG Index;
+ UCHAR WSMStatus;
+ PUCHAR Address;
+
+ //
+ // Concoct the base address of this ROM chip.
+ //
+
+ Address = (PUCHAR)
+ ((ULONG)WriteAddress &
+ ~(RomValues[MachineROMType].BytesPerChip - 1));
+
+ FwROMResetStatus(WriteAddress);
+
+ for (Index = 0; Index < 20; Index++) {
+
+
+ WRITE_PORT_UCHAR (Address+0x5555, 0xaa);
+ VenStallExecution(2);
+ WRITE_PORT_UCHAR (Address+0x2aaa, 0x55);
+ VenStallExecution(2);
+ WRITE_PORT_UCHAR (Address+0x5555, 0xa0);
+ VenStallExecution(2);
+ WRITE_PORT_UCHAR (WriteAddress, WriteData);
+ VenStallExecution(2);
+
+ if (CheckAM29F010Status(FALSE, WriteAddress, WriteData) != ESUCCESS) {
+
+ //
+ // The write failed. Ensure status is clear and see if we
+ // can retry.
+ //
+
+ FwROMResetStatus(WriteAddress);
+ FwROMSetReadMode(WriteAddress);
+ VenPrint2("? Write failed to address %x. Wrote %x, ",
+ WriteAddress, WriteData);
+ VenPrint1("verify returns %x.\r\n",
+ READ_PORT_UCHAR((PUCHAR)WriteAddress));
+
+ if (READ_PORT_UCHAR(WriteAddress) != 0xff) {
+ VenPrint("RETRY ABORTED!\r\n");
+ return EIO;
+ } else {
+ VenPrint("Retrying..\r\n");
+ }
+
+ } else {
+
+ //
+ // The write succeeded.
+ //
+
+ return ESUCCESS;
+ }
+
+ }
+
+
+ //
+ // We failed to write the byte after 20 tries.
+ //
+
+ return EIO;
+}
+
+
+ARC_STATUS
+FwROMDetermineMachineROMType (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This determines what kind of Flash ROM is in the machine.
+
+ The ROMs making up the Flash ROM space are assumed to be
+ homogeneous. So, we only check one chip.
+
+ N.B. The RomValues array must be tested in ascending order,
+
+ N.B. This function must not call any of the FwROM... functions!
+
+Arguments:
+
+ ROMType - A pointer to a variable that will receive the type
+ of ROM in the machine, if the return value is ESUCCESS.
+
+ROM state on exit:
+
+ Left in read-array mode.
+
+Return Value:
+
+ ESUCCESS if we could successfully identify the ROM.
+ Otherwise, and error condition.
+
+--*/
+
+{
+ BOOLEAN Match;
+ ROM_TYPE Index;
+ ULONG IDIndex;
+ PUCHAR ChipAddress;
+
+ //
+ // Loop through each ROM type, trying the ID Command Sequence for
+ // each.
+ //
+
+ for (Index = 0; Index < InvalidROM; Index++) {
+
+ //
+ // Send the command.
+ //
+
+ for (IDIndex = 0;
+ IDIndex < RomValues[Index].IdCommandLength;
+ IDIndex++) {
+
+ WRITE_PORT_UCHAR(RomValues[Index].IdCommand[IDIndex].Address,
+ RomValues[Index].IdCommand[IDIndex].Value);
+
+ VenStallExecution(15);
+ }
+
+ //
+ // Check the response.
+ //
+
+ Match = TRUE;
+
+ for (IDIndex = 0;
+ IDIndex < RomValues[Index].IdResponseLength;
+ IDIndex++) {
+
+ if (RomValues[Index].IdResponse[IDIndex].Value !=
+ READ_PORT_UCHAR(RomValues[Index].IdResponse[IDIndex].Address)) {
+ //
+ // This portion of the Response sequence did not match.
+ //
+
+ Match = FALSE;
+ break;
+ }
+ }
+
+ if (Match == FALSE) {
+ continue;
+ }
+
+ //
+ // We have found a match. Set all the ROMs to read-array mode, and
+ // then return the current entry as the ROM type. This should not
+ // be necessary on a cold-start, but may be necessary on a warm
+ // restart if the ROMs have been left in an inconsistent state by the
+ // HAL.
+ //
+
+ MachineROMType = RomValues[Index].ROMType;
+
+ ChipAddress = (PUCHAR)PROM_VIRTUAL_BASE;
+
+ for (IDIndex = 0;
+ IDIndex < (ONE_MB / RomValues[MachineROMType].BytesPerChip);
+ IDIndex++) {
+ FwROMResetStatus(ChipAddress);
+ FwROMSetReadMode(ChipAddress);
+ ChipAddress += RomValues[MachineROMType].BytesPerChip;
+ }
+
+ return (ESUCCESS);
+ }
+
+ //
+ // We have not found a match. Return an error.
+ //
+
+ return (EIO);
+}
+
+VOID
+FwROMResetStatus(
+ IN PUCHAR Address
+ )
+/*++
+
+Routine Description:
+
+ This clears the status register in a ROM chip.
+
+Arguments:
+
+ Address - An address within the chip that is to be reset.
+
+ROM state on exit:
+
+ The status register is left in a cleared (reset) state.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG Index;
+
+ //
+ // Concoct the base address of this ROM chip.
+ //
+ // Remember, C is call by value!
+ //
+
+ Address = (PUCHAR)
+ ((ULONG)Address & ~(RomValues[MachineROMType].BytesPerChip - 1));
+
+ for (Index = 0;
+ Index < RomValues[MachineROMType].ResetCommandLength;
+ Index++) {
+ WRITE_PORT_UCHAR (Address +
+ RomValues[MachineROMType].ResetCommand[Index].Offset,
+ RomValues[MachineROMType].ResetCommand[Index].Value);
+ AlphaInstMB();
+ VenStallExecution(RomValues[MachineROMType].StallAmount);
+ }
+}
+
+VOID
+FwROMSetReadMode(
+ IN PUCHAR Address
+ )
+/*++
+
+Routine Description:
+
+ This returns a ROM chip to read-array mode.
+
+Arguments:
+
+ Address - An address within the chip that is to be set to
+ read-array mode.
+
+ROM state on exit:
+
+ The chip is left in read-array mode.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG Index;
+
+ //
+ // Concoct the base address of this ROM chip.
+ //
+ // Remember, C is call by value!
+ //
+
+ Address = (PUCHAR)
+ ((ULONG)Address & ~(RomValues[MachineROMType].BytesPerChip - 1));
+
+ for (Index = 0;
+ Index < RomValues[MachineROMType].ReadCommandLength;
+ Index++) {
+ WRITE_PORT_UCHAR (Address +
+ RomValues[MachineROMType].ReadCommand[Index].Offset,
+ RomValues[MachineROMType].ReadCommand[Index].Value);
+ AlphaInstMB();
+ VenStallExecution(RomValues[MachineROMType].StallAmount);
+ }
+}
+
+VOID
+FwROMSetARCDataToReadMode (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine sets the virtual 64KB ROM block that houses the
+ CDS tree, environment variables, and EISA configuration data to
+ read-array mode. For devices with a block size smaller than
+ 64KB, we issues set read-mode commands to every block within this
+ virtual 64KB block. This is overkill, but it is easy.
+
+Arguments:
+
+ None.
+
+ROM state on exit:
+
+ Set to read-array mode.
+
+Return Value:
+
+ None
+
+--*/
+{
+ PUCHAR Address;
+ ULONG Index;
+
+ Address = (PUCHAR)NVRAM_CONFIGURATION;
+
+ //
+ // Hackhack: At some point change this to eliminate the division.
+ //
+
+ for (Index = 0;
+ Index < (SIXTY_FOUR_KB / RomValues[MachineROMType].BytesPerBlock);
+ Index++) {
+ FwROMSetReadMode(Address);
+ Address += RomValues[MachineROMType].BytesPerBlock;
+ }
+}
+
+ARC_STATUS
+FwROMByteWrite(
+ IN PUCHAR WriteAddress,
+ IN UCHAR WriteData
+ )
+
+/*++
+
+Routine Description:
+
+ This writes a byte in the Alpha/Jensen ROM space.
+
+Arguments:
+
+ WriteAddress = meta-virtual address of the byte to be written.
+ WriteData = byte to be written.
+
+ROM state on exit:
+
+ The byte is written, and the WSM status register is modified.
+
+Return Value:
+
+ Whatever is returned from the ROM-specific write function.
+
+--*/
+
+{
+ return ((*RomValues[MachineROMType].ByteWrite)(WriteAddress, WriteData));
+}
+
+ARC_STATUS
+FwROMEraseBlock(
+ IN PUCHAR EraseAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This erases a single block in the Alpha/Jensen ROM space. The number
+ of bytes erased is dependent on the underlying chip being manipulated.
+
+Arguments:
+
+ EraseAddress - An address within the block to be erased.
+
+ROM state on exit:
+
+ On a successful return, the status register is left in a reset state and
+ the ROM is in read-array mode.
+
+Return Value:
+
+ Whatever is returned from the ROM-specific erase function.
+
+--*/
+
+{
+ return ((*RomValues[MachineROMType].SectorErase)(EraseAddress));
+}
+
+ARC_STATUS
+FwROMErase64KB(
+ IN PUCHAR EraseAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This erases a 64KB logical block in the Alpha/Jensen ROM space.
+
+ To minimize code changes with the previous version of the firmware,
+ the PROM space is treated as though it has a block size of 64KB, even
+ if the block size is must less than that.
+
+Arguments:
+
+ EraseAddress - An address within the block to be erased.
+
+ROM state on exit:
+
+ On a successful return, the status register is left in a reset state and
+ the ROM is in read-array mode.
+
+Return Value:
+
+ Returns ESUCCESS if the erase was successful.
+ Otherwise, EIO is returned.
+
+--*/
+
+{
+ ARC_STATUS Status;
+ ULONG Index;
+
+ //
+ // Create the base address of the 64KB block to be cleared.
+ //
+ // Remember, C is call by value!
+ //
+
+ EraseAddress = (PUCHAR)((ULONG)EraseAddress & ~(SIXTY_FOUR_KB - 1));
+
+ //
+ // Now erase as many blocks as is necessary to erase a 64KB virtual block.
+ //
+ // Hack: I should eliminate the integer division.
+ //
+
+ for (Index = 0;
+ Index < (SIXTY_FOUR_KB / RomValues[MachineROMType].BytesPerBlock);
+ Index++) {
+
+ if ((Status = (*RomValues[MachineROMType].SectorErase)(EraseAddress))
+ != ESUCCESS) {
+ break;
+ }
+
+ EraseAddress += RomValues[MachineROMType].BytesPerBlock;
+ }
+
+ return (Status);
+}
diff --git a/private/ntos/fw/alpha/rom.h b/private/ntos/fw/alpha/rom.h
new file mode 100644
index 000000000..3b79dea8b
--- /dev/null
+++ b/private/ntos/fw/alpha/rom.h
@@ -0,0 +1,182 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ rom.h
+
+Abstract:
+
+ This module defines structures and datatypes for use in reading
+ and writing ROMs/PROMs/Flash ROMs.
+
+ Neither this file or rom.c makes an attempt at universal ROM support.
+
+Author:
+
+ John DeRosa 4-May-1993
+
+Revision History:
+
+--*/
+
+//
+// All ROM manipulations (reading, writing, etc.) are done through
+// an array. The array contains one entry per ROM type, and the values
+// in each entry dictate how to talk to the ROM.
+//
+// Supported ROMs are assumed to have the following characteristics:
+//
+// The ROM space in the machine is made up of all the same parts.
+// I.e., the space is homogeneous.
+//
+// Each chip has a byte path for data in and data out.
+//
+// Each chip has a way to identify itself.
+//
+// Each chip has a way to be reset.
+//
+// Each chip has a finite erase, write, set read-mode, and identify
+// sequence.
+//
+// The chip block size is less than or equal to 64KB.
+//
+
+//
+// Define the maximum length of certain commands.
+//
+
+#define MAXIMUM_ROM_ID_COMMAND_LENGTH 3
+#define MAXIMUM_ROM_ID_RESPONSE_LENGTH 2
+#define MAXIMUM_ROM_READ_COMMAND_LENGTH 3
+#define MAXIMUM_ROM_RESET_COMMAND_LENGTH 3
+
+
+//
+// Define function time for erase and byte-write entries.
+//
+
+typedef ARC_STATUS (*PROMSECTORERASE) (IN PUCHAR EraseAddress);
+
+typedef ARC_STATUS (*PROMBYTEWRITE) (IN PUCHAR WriteAddress,
+ IN UCHAR WriteData);
+
+//
+// Define structure to store ROM address and byte pairs.
+//
+
+typedef struct _ABSOLUTE_ROM_COMMAND {
+ PUCHAR Address;
+ UCHAR Value;
+} ABSOLUTE_ROM_COMMAND, *PABSOLUTE_ROM_COMMAND;
+
+typedef struct _OFFSET_ROM_COMMAND {
+ ULONG Offset;
+ UCHAR Value;
+} OFFSET_ROM_COMMAND, *POFFSET_ROM_COMMAND;
+
+//
+// Define the entries in the ROM values table. These are organized for
+// memory efficiency.
+//
+
+typedef struct _ROM_VALUES {
+
+ //
+ // Microseconds to stall after most ROM commands.
+ //
+
+ UCHAR StallAmount;
+
+ //
+ // Length of the Identification command sequence.
+ //
+
+ UCHAR IdCommandLength;
+
+ //
+ // Length of the Identification response.
+ //
+
+ UCHAR IdResponseLength;
+
+ //
+ // Length of the Reset command.
+ //
+
+ UCHAR ResetCommandLength;
+
+ //
+ // Length of the Set read-mode command.
+ //
+
+ UCHAR ReadCommandLength;
+
+ //
+ // The ROM supported by this entry.
+ //
+
+ ROM_TYPE ROMType;
+
+ //
+ // Number of bytes per chip.
+ //
+
+ ULONG BytesPerChip;
+
+ //
+ // Number of bytes per block.
+ //
+
+ ULONG BytesPerBlock;
+
+ //
+ // Identification command sequence.
+ //
+ // Each step in the sequence is two bytes: address to be written,
+ // and data to be written.
+ //
+
+ ABSOLUTE_ROM_COMMAND IdCommand[MAXIMUM_ROM_ID_COMMAND_LENGTH];
+
+ //
+ // Identification response sequence.
+ //
+ // Each step in the seqeuence is two bytes: address to be read, and
+ // the byte that should be returned.
+ //
+
+ ABSOLUTE_ROM_COMMAND IdResponse[MAXIMUM_ROM_ID_RESPONSE_LENGTH];
+
+ //
+ // Reset command sequence.
+ //
+ // Each step in the sequence is two bytes: address to be written,
+ // and data to be written.
+ //
+
+ OFFSET_ROM_COMMAND ResetCommand[MAXIMUM_ROM_RESET_COMMAND_LENGTH];
+
+ //
+ // Set read-mode command sequence.
+ //
+ // Each step in the sequence is two bytes: address to be written,
+ // and data to be written.
+ //
+
+ OFFSET_ROM_COMMAND ReadCommand[MAXIMUM_ROM_READ_COMMAND_LENGTH];
+
+ //
+ // The function to be called to do a block erase.
+ //
+
+ PROMSECTORERASE SectorErase;
+
+ //
+ // The function to be called to do a byte write.
+ //
+
+ PROMBYTEWRITE ByteWrite;
+
+} ROM_VALUES, *PROM_VALUES;
diff --git a/private/ntos/fw/alpha/selfmap.h b/private/ntos/fw/alpha/selfmap.h
new file mode 100644
index 000000000..50e51ddc4
--- /dev/null
+++ b/private/ntos/fw/alpha/selfmap.h
@@ -0,0 +1,439 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ selfmap.h
+
+Abstract:
+
+ This module defines various memory addresses for the ROM self-test.
+ For Alpha/Jensen, most of this module is unused.
+
+
+Author:
+
+ Lluis Abello (lluis) 10-Jan-1991
+
+Revision History:
+
+ John DeRosa [DEC] 29-June-1992
+
+ Added Alpha/Jensen modifications.
+
+--*/
+
+#ifndef _SELFMAP_
+#define _SELFMAP_
+
+
+//
+// All of the following is unused in Alpha PCs at the moment.
+//
+
+#ifndef ALPHA
+
+#define PROM256
+
+#ifdef PROM64
+#define ROM_SIZE 0x10000
+#endif
+#ifdef PROM128
+#define ROM_SIZE 0x20000
+#endif
+#ifdef PROM256
+#define ROM_SIZE 0x40000
+#endif
+
+//
+// TTable points to 2Mb
+//
+#define TT_BASE_ADDRESS 0x200000
+
+#define MEMTEST_SIZE 0x2000 // Size of memory tested first
+#define STACK_SIZE 0xA000 // 40Kb of stack
+#define RAM_TEST_STACK_ADDRESS 0x8000BFF0 // Stack for code copied to memory
+
+#ifdef R3000
+#define INSTRUCTION_CACHE_SIZE 0x10000 // 64Kb of I Cache
+#define DATA_CACHE_SIZE 0x10000 // 64Kb of D Cache
+#define SIZE_OF_CACHES 0x10000 // 64Kb bigest cache.
+#define ROM_TLB_ENTRIES (ROM_SIZE >> 12)
+#define DEVICE_TLB_ENTRIES 16
+#define FIRST_UNUSED_TLB_ENTRY ROM_TLB_ENTRIES+DEVICE_TLB_ENTRIES
+#endif // R3000
+
+//
+// Define firmware size.
+// Firmware size includes code and stack.
+//
+// FW_TOP_ADDRESS must be a 64K aligned address.
+// The upper 64Kb (0x40000 to 0x50000) are reserved for the video prom code.
+//
+//
+
+#define VIDEO_PROM_SIZE 0x10000
+
+#define FW_SIZE 0x40000
+
+#define FW_TOP_ADDRESS (FW_SIZE+VIDEO_PROM_SIZE)
+
+#define FW_PAGES ((FW_TOP_ADDRESS) >> PAGE_SHIFT)
+
+#define VIDEO_PROM_CODE_VIRTUAL_BASE 0x10000000 // Link address of video prom code
+#define VIDEO_PROM_CODE_PHYSICAL_BASE FW_SIZE // phys address of video prom code
+#define VIDEO_PROM_CODE_UNCACHED_BASE KSEG1_BASE+FW_SIZE // uncached address where video prom code is copied to
+
+
+
+
+//
+// Address definitions for the SelftTests written in C.
+// The code is copied to RAM_TEST_LINK_ADDRESS from RAM_TEST_ROM_ADDRESS
+// so that it runs at the address it was linked.
+//
+
+#define RAM_TEST_DESTINATION_ADDRESS 0xA000c000 // uncached link address
+#define RAM_TEST_LINK_ADDRESS 0x8000c000 // Link Address of code
+
+//
+// FW_TOP_ADDRESS ___________
+// | Video rom |
+// | code |
+// |___________|
+// FW_SIZE | Code |
+// | & |
+// | Data |
+// | |
+// |___________|
+// | Stack || |
+// |_______\/__|
+// MEMTEST_SIZE |PutLed | Memory tested from ROM
+// |ZeroMem |
+// |MemoryTest |
+// 0 |___________|
+//
+
+#define LINK_ADDRESS 0xE1000000
+#define RESET_VECTOR 0xBFC00000
+
+//
+// Virtual - Physiscal base address pairs
+//
+#define TLB_TEST_PHYS 0x0 // To test the tlb
+#define TLB_TEST_VIRT 0x20000000 //
+#define RESV_VIRT 0xE4000000
+
+//
+// Entry LO - HI pairs
+//
+#ifdef R4000
+#define PROM_HI ((PROM_VIRTUAL_BASE >> 13) << ENTRYHI_VPN2)
+#define PROM_LO0 ((PROM_PHYSICAL_BASE >> 12) << ENTRYLO_PFN) + (1 << ENTRYLO_G) + (1 << ENTRYLO_V) + (2 << ENTRYLO_C)
+#ifdef PROM256
+#define PROM_LO1 (1 << ENTRYLO_G)
+#define PROM_MASK (PAGEMASK_256KB << PAGEMASK_PAGEMASK)
+#endif
+#ifdef PROM128 //
+#define PROM_LO1 (((PROM_PHYSICAL_BASE+0x10000) >> 12) << ENTRYLO_PFN) + (1 << ENTRYLO_G) + \
+ (1 << ENTRYLO_V) + (2 << ENTRYLO_C)
+#define PROM_MASK (PAGEMASK_64KB << PAGEMASK_PAGEMASK)
+#endif
+#ifdef PROM64
+#define PROM_LO1 (1 << ENTRYLO_G) // If odd page not used
+#define PROM_MASK (PAGEMASK_64KB << PAGEMASK_PAGEMASK)
+#endif
+#define TLB_TEST_LO ((1 << ENTRYLO_G) + (1 << ENTRYLO_V) + \
+ (1 << ENTRYLO_D) + (2 << ENTRYLO_C) + TLB_TEST_PHYS)
+
+#define TLB_TEST_HI TLB_TEST_VIRT
+
+#define TLB_KSEG_PHYS 0x0
+#define TLB_KSEG_LO ((1 << ENTRYLO_G) + (1 << ENTRYLO_V) + \
+ (1 << ENTRYLO_D) + (3 << ENTRYLO_C) + TLB_KSEG_PHYS)
+#define TLB_KSEG_VIRT 0x10000000
+#define TLB_KSEG_HI TLB_KSEG_VIRT
+#define TLB_KSEG_MASK (PAGEMASK_64KB << PAGEMASK_PAGEMASK)
+#endif // R4000
+
+#ifdef R3000
+//
+// Entry LO - HI pairs
+//
+#define DIAGNOSTIC_PHYSICAL_BASE 0x8000F000
+
+#define LED_LO ((1 << ENTRYLO_G) | (1 << ENTRYLO_V) | \
+ (1 << ENTRYLO_N) | (1 << ENTRYLO_D) | \
+ DIAGNOSTIC_PHYSICAL_BASE)
+#define LED_HI DIAGNOSTIC_VIRTUAL_BASE
+
+#define TLB_TEST_LO ((1 << ENTRYLO_G) | (1 << ENTRYLO_V) | \
+ (1 << ENTRYLO_N) | (1 << ENTRYLO_D) | \
+ TLB_TEST_PHYS)
+#define TLB_TEST_HI TLB_TEST_VIRT
+
+#define ROM_LO ((1 << ENTRYLO_G) | (1 << ENTRYLO_V) | \
+ (1 << ENTRYLO_N) | \
+ PROM_PHYSICAL_BASE)
+#define ROM_HI PROM_VIRTUAL_BASE
+
+#define DEVICE_LO ((1 << ENTRYLO_G) | (1 << ENTRYLO_V) | \
+ (1 << ENTRYLO_N) | (1 << ENTRYLO_D) | \
+ DEVICE_PHYSICAL_BASE)
+#define DEVICE_HI DEVICE_VIRTUAL_BASE
+
+#define PROC_LO ((1 << ENTRYLO_G) | (1 << ENTRYLO_V) | \
+ (1 << ENTRYLO_N) | \
+ INTERRUPT_PHYSICAL_BASE)
+#define PROC_HI INTERRUPT_VIRTUAL_BASE
+
+#define VID_LO ((1 << ENTRYLO_G) | (1 << ENTRYLO_V) | \
+ (1 << ENTRYLO_N) | (1 << ENTRYLO_D) | \
+ VIDEO_CONTROL_PHYSICAL_BASE)
+#define VID_HI VIDEO_CONTROL_VIRTUAL_BASE
+
+#define VIDMEM_LO ((1 << ENTRYLO_G) | (1 << ENTRYLO_V) | \
+ (1 << ENTRYLO_N) | (1 << ENTRYLO_D) | \
+ VIDEO_MEMORY_PHYSICAL_BASE)
+#define VIDMEM_HI VIDEO_MEMORY_PHYSICAL_BASE
+
+
+#define CURSOR_LO ((1 << ENTRYLO_G) | (1 << ENTRYLO_V) | \
+ (1 << ENTRYLO_N) | (1 << ENTRYLO_D) | \
+ VIDEO_CURSOR_PHYSICAL_BASE)
+#define CURSOR_HI VIDEO_CURSOR_VIRTUAL_BASE
+
+#define RESV_LO ((1 << ENTRYLO_G) | (1 << ENTRYLO_N))
+#define RESV_HI RESV_VIRT
+
+#endif //R3000
+
+
+
+#endif // ALPHA
+
+#ifndef ALPHA
+
+//
+// Trap handling definitions.
+//
+#define COMMON_EXCEPTION 0
+#define NMI_EXCEPTION 1
+#define CACHE_EXCEPTION 2
+
+
+
+//
+// Define offsets from Register Table.
+// Must match the definiton in monitor.h
+//
+#define zeroRegTable 0x0
+#define atRegTable 0x4
+#define v0RegTable 0x8
+#define v1RegTable 0xC
+#define a0RegTable 0x10
+#define a1RegTable 0x14
+#define a2RegTable 0x18
+#define a3RegTable 0x1C
+#define t0RegTable 0x20
+#define t1RegTable 0x24
+#define t2RegTable 0x28
+#define t3RegTable 0x2C
+#define t4RegTable 0x30
+#define t5RegTable 0x34
+#define t6RegTable 0x38
+#define t7RegTable 0x3C
+#define s0RegTable 0x40
+#define s1RegTable 0x44
+#define s2RegTable 0x48
+#define s3RegTable 0x4C
+#define s4RegTable 0x50
+#define s5RegTable 0x54
+#define s6RegTable 0x58
+#define s7RegTable 0x5C
+#define t8RegTable 0x60
+#define t9RegTable 0x64
+#define k0RegTable 0x68
+#define k1RegTable 0x6C
+#define gpRegTable 0x70
+#define spRegTable 0x74
+#define s8RegTable 0x78
+#define raRegTable 0x7C
+#define f0RegTable 0x80
+#define f1RegTable 0x84
+#define f2RegTable 0x88
+#define f3RegTable 0x8C
+#define f4RegTable 0x90
+#define f5RegTable 0x94
+#define f6RegTable 0x98
+#define f7RegTable 0x9C
+#define f8RegTable 0xA0
+#define f9RegTable 0xA4
+#define f10RegTable 0xA8
+#define f11RegTable 0xAC
+#define f12RegTable 0xB0
+#define f13RegTable 0xB4
+#define f14RegTable 0xB8
+#define f15RegTable 0xBC
+#define f16RegTable 0xC0
+#define f17RegTable 0xC4
+#define f18RegTable 0xC8
+#define f19RegTable 0xCC
+#define f20RegTable 0xD0
+#define f21RegTable 0xD4
+#define f22RegTable 0xD8
+#define f23RegTable 0xDC
+#define f24RegTable 0xE0
+#define f25RegTable 0xE4
+#define f26RegTable 0xE8
+#define f27RegTable 0xEC
+#define f28RegTable 0xF0
+#define f29RegTable 0xF4
+#define f30RegTable 0xF8
+#define f31RegTable 0xFC
+#define fsrRegTable 0x100
+#define indexRegTable 0x104
+#define randomRegTable 0x108
+#define entrylo0RegTable 0x10C
+#define entrylo1RegTable 0x110
+#define contextRegTable 0x114
+#define pagemaskRegTable 0x118
+#define wiredRegTable 0x11C
+#define badvaddrRegTable 0x120
+#define countRegTable 0x124
+#define entryhiRegTable 0x128
+#define compareRegTable 0x12C
+#define psrRegTable 0x130
+#define causeRegTable 0x134
+#define epcRegTable 0x138
+#define pridRegTable 0x13C
+#define configRegTable 0x140
+#define lladdrRegTable 0x144
+#define watchloRegTable 0x148
+#define watchhiRegTable 0x14C
+#define eccRegTable 0x150
+#define cacheerrorRegTable 0x154
+#define tagloRegTable 0x158
+#define taghiRegTable 0x15C
+#define errorepcRegTable 0x160
+#define RegisterTableSize 0x164
+
+//
+// Define Fw exception frame offsets.
+//
+
+#define FwFrameK1 0x4
+#define FwFrameRa 0x8
+#define FwFrameA0 0xC
+#define FwFrameA1 0x10
+#define FwFrameA2 0x14
+#define FwFrameA3 0x18
+#define FwFrameV0 0x1C
+#define FwFrameV1 0x20
+#define FwFrameT0 0x24
+#define FwFrameT1 0x28
+#define FwFrameT2 0x2C
+#define FwFrameT3 0x30
+#define FwFrameT4 0x34
+#define FwFrameT5 0x38
+#define FwFrameT6 0x3C
+#define FwFrameT7 0x40
+#define FwFrameT8 0x44
+#define FwFrameT9 0x48
+#define FwFrameAT 0x4C
+#define FwFrameSize 0x50
+
+
+
+#endif // ALPHA
+
+
+#ifdef ALPHA
+
+//
+// Define offsets from Register Table.
+// Must match the definiton in monitor.h
+//
+
+#define ResExceptTypeRegTable 0x0
+#define ep1RegTable 0x8
+#define ep2RegTable 0x10
+#define ep3RegTable 0x18
+#define ep4RegTable 0x20
+#define ep5RegTable 0x28
+#define epsrRegTable 0x30
+#define emmcsrRegTable 0x38
+#define evaRegTable 0x40
+#define epcRegTable 0x48
+#define v0RegTable 0x50
+#define t0RegTable 0x58
+#define t1RegTable 0x60
+#define t2RegTable 0x68
+#define t3RegTable 0x70
+#define t4RegTable 0x78
+#define t5RegTable 0x80
+#define t6RegTable 0x88
+#define t7RegTable 0x90
+#define s0RegTable 0x98
+#define s1RegTable 0xa0
+#define s2RegTable 0xa8
+#define s3RegTable 0xb0
+#define s4RegTable 0xb8
+#define s5RegTable 0xc0
+#define fpRegTable 0xc8
+#define a0RegTable 0xd0
+#define a1RegTable 0xd8
+#define a2RegTable 0xe0
+#define a3RegTable 0xe8
+#define a4RegTable 0xf0
+#define a5RegTable 0xf8
+#define t8RegTable 0x100
+#define t9RegTable 0x108
+#define t10RegTable 0x110
+#define t11RegTable 0x118
+#define raRegTable 0x120
+#define t12RegTable 0x128
+#define atRegTable 0x130
+#define gpRegTable 0x138
+#define spRegTable 0x140
+#define zeroRegTable 0x148
+#define f0RegTable 0x150
+#define f1RegTable 0x158
+#define f2RegTable 0x160
+#define f3RegTable 0x168
+#define f4RegTable 0x170
+#define f5RegTable 0x178
+#define f6RegTable 0x180
+#define f7RegTable 0x188
+#define f8RegTable 0x190
+#define f9RegTable 0x198
+#define f10RegTable 0x1a0
+#define f11RegTable 0x1a8
+#define f12RegTable 0x1b0
+#define f13RegTable 0x1b8
+#define f14RegTable 0x1c0
+#define f15RegTable 0x1c8
+#define f16RegTable 0x1d0
+#define f17RegTable 0x1d8
+#define f18RegTable 0x1e0
+#define f19RegTable 0x1e8
+#define f20RegTable 0x1f0
+#define f21RegTable 0x1f8
+#define f22RegTable 0x200
+#define f23RegTable 0x208
+#define f24RegTable 0x210
+#define f25RegTable 0x218
+#define f26RegTable 0x220
+#define f27RegTable 0x228
+#define f28RegTable 0x230
+#define f29RegTable 0x238
+#define f30RegTable 0x240
+#define f31RegTable 0x248
+#define RegisterTableSize 0x250
+
+
+#endif // ALPHA
+
+#endif // _SELFMAP_
diff --git a/private/ntos/fw/alpha/selftest.h b/private/ntos/fw/alpha/selftest.h
new file mode 100644
index 000000000..c642fd2e3
--- /dev/null
+++ b/private/ntos/fw/alpha/selftest.h
@@ -0,0 +1,119 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ selftest.h
+
+Abstract:
+
+ This module contains definitions for selftest.c
+
+Author:
+
+ Lluis Abello (lluis) 03-Jan-1991
+
+Environment:
+
+
+Revision History:
+
+ 21-May-1992 John DeRosa [DEC]
+
+ Modified for the Alpha/Jensen machine. Definitions not needed are
+ commented out.
+
+ 31-March-1993 Bruce Butts [DEC]
+
+ Modified for the Alpha/Morgan machine. Definitions not needed are
+ commented out.
+
+--*/
+
+//
+// These were defined for the Jazz machine, and are unneeded for Alpha/Jensen.
+//
+
+#ifndef ALPHA // (JENSEN || MORGAN)
+//
+// Video Memory Test
+//
+
+#define VIDEO_MEMORY_SIZE 0x200000 // 2 MB
+#define DISPLAY_MEMORY_SIZE 0x100000 // 1 MB
+
+//
+// Memory test stuff
+//
+
+#define TESTED_KB (FW_TOP_ADDRESS>>10)
+#define KB_OF_MEMORY (MEMORY_SIZE>>10) //
+#define KB_PER_TEST 0x400 // 1024K at a time
+#define NVRAM_TEST_END 0x800
+
+typedef ULONG (* TestRoutine)(VOID);
+typedef VOID (* LED_ROUTINE)(ULONG);
+
+#define PutLedDisplay ((LED_ROUTINE) PROM_ENTRY(14))
+
+#endif // ALPHA
+
+//
+// Declare static variables
+//
+
+#ifndef ALPHA // (JENSEN || MORGAN)
+
+extern BOOLEAN LanAddress; // True if station address is OK False Otherwise
+extern BOOLEAN ConfigurationBit; // read value from diagnostic register
+extern BOOLEAN LoopOnError; // read value from diagnostic register
+extern BOOLEAN IgnoreErrors; // read value from diagnostic register
+extern BOOLEAN VideoReady; // True if display on video monitor
+
+#endif // ALPHA
+
+extern volatile LONG TimerTicks; // Counter for timeouts
+
+//
+// Routine declaration.
+//
+//BOOLEAN ExecuteTest(TestRoutine,ULONG);
+//ULONG RomVideoMemory();
+//ULONG RomReadMergeWrite();
+//ULONG RomIOCacheTest();
+//ULONG RomSonicResetTest();
+//ULONG RomSonicLoopBackTest();
+//ULONG RomFloppyResetTest();
+//ULONG RomScsiResetTest();
+//ULONG RomSerialResetTest();
+//ULONG RomSerial1RegistersTest();
+//ULONG RomSerial2RegistersTest();
+//ULONG RomSerial1LoopBackTest();
+//ULONG RomSerial2LoopBackTest();
+//ULONG RomParallelRegistersTest();
+//ULONG RomScsiRegistersTest();
+//ULONG InterruptControllerTest();
+ULONG ConnectInterrupts();
+ULONG DisableInterrupts();
+//ULONG RomRTCTest();
+ULONG InitMouse();
+BOOLEAN InitKeyboard();
+ULONG InitKeyboardController();
+//ULONG RomNvramTest();
+//VOID RomBeep();
+ULONG RomInitISP (VOID);
+
+char * HANG_MSG = "\r\nSelf-test failed.";
+
+#define CHECK_ULONG(Address,Value) if (READ_PORT_ULONG(Address) != Value) {\
+ Errors++;\
+ }
+#define CHECK_USHORT(Address,Value) if (READ_PORT_USHORT(Address) != Value) { \
+ Errors++;\
+ }
+#define CHECK_UCHAR(Address,Value) if (READ_PORT_UCHAR(Address) != Value) { \
+ Errors++;\
+ }
+
diff --git a/private/ntos/fw/alpha/stubs.c b/private/ntos/fw/alpha/stubs.c
new file mode 100644
index 000000000..c64c86266
--- /dev/null
+++ b/private/ntos/fw/alpha/stubs.c
@@ -0,0 +1,376 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ stubs.c
+
+Abstract:
+
+ This module implements stub routines for the firmware, FailSafe
+ Booter, and the Alpha AXP/Jensen ROM update tool (JNUPDATE.EXE).
+
+Author:
+
+ Lluia Abello (lluis) 3-Oct-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ John DeRosa [DEC] 11-May-1993
+
+ Made Alpha AXP modification.
+
+--*/
+
+#include "ntos.h"
+#include "fwp.h"
+#include "fwstring.h"
+
+LONG
+DebugPrint(
+ IN PSTRING Output
+ );
+
+
+#if defined(MORGAN)
+#include "ex.h"
+
+PVOID
+ExAllocatePool(
+ IN POOL_TYPE PoolType,
+ IN ULONG NumberOfBytes
+ )
+{
+ return((PVOID)NULL);
+}
+
+
+
+VOID
+KeRaiseIrql (
+ KIRQL NewIrql,
+ PKIRQL OldIrql
+ )
+{
+ return;
+}
+
+
+
+VOID
+KeLowerIrql (
+ KIRQL NewIrql
+ )
+{
+ return;
+}
+
+
+#endif // MORGAN
+
+
+
+#ifndef JNUPDATE
+
+VOID
+FwpFreeStub(
+ IN PVOID Buffer
+ )
+{
+}
+
+VOID
+FwpReservedRoutine(
+ VOID
+ )
+{
+ FwPrint(ST_RESERVED_ROUTINE_MSG);
+ return;
+}
+
+#endif
+
+
+
+//
+// This is defined in ntos\rtl\imagedir.c. This is linked in unnecessarily
+// on a normal build, and is needed on a kd build. The problem is that the
+// rtl copy has an try/except block, which causes SEH code to be pulled into
+// the link, which we are not prepared for. So, this copy is identical to
+// the rtl copy except it has no try/except form.
+//
+
+PIMAGE_NT_HEADERS
+RtlImageNtHeader (
+ IN PVOID Base
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the address of the NT Header.
+
+Arguments:
+
+ Base - Supplies the base of the image.
+
+Return Value:
+
+ Returns the address of the NT Header.
+
+--*/
+
+{
+
+ PIMAGE_NT_HEADERS NtHeaders;
+
+ if (Base != NULL &&
+ Base != (PVOID)-1
+ ) {
+// try {
+ if (((PIMAGE_DOS_HEADER)Base)->e_magic == IMAGE_DOS_SIGNATURE) {
+ NtHeaders = (PIMAGE_NT_HEADERS)((PCHAR)Base + ((PIMAGE_DOS_HEADER)Base)->e_lfanew);
+ if (NtHeaders->Signature == IMAGE_NT_SIGNATURE) {
+ return NtHeaders;
+ }
+ }
+
+// } except(EXCEPTION_EXECUTE_HANDLER) {
+// return NULL;
+// }
+
+ }
+
+ return NULL;
+}
+
+
+
+
+#ifndef JNUPDATE
+
+#ifndef ALPHA_FW_KDHOOKS
+
+//
+// This must not be defined for kd link.
+//
+
+LONG
+DebugPrint(
+ IN PSTRING Output
+ )
+
+/*++
+
+Routine Description:
+
+ This function is defined in rtl\alpha\debugstb.s. There, it calls
+ BREAK_DEBUG_PRINT, which is defined in public\sdk\inc\kxalpha.h to
+ do a call_pal callkd, which in the NT PALcode will invoke the
+ AlphaKd link.
+
+ The normal firmware PALcode has no AlphaKd support, so DebugPrint is
+ stubbed off here. There are references to DebugPrint in the bldr
+ directory and some fw files.
+
+Arguments:
+
+
+Return Value:
+
+--*/
+
+{
+ return (0);
+}
+
+#endif
+
+#endif
+
+
+#ifndef JNUPDATE
+
+VOID
+RtlInitString(
+ OUT PSTRING DestinationString,
+ IN PCSZ SourceString OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ The RtlInitString function initializes an NT counted string.
+ The DestinationString is initialized to point to the SourceString
+ and the Length and MaximumLength fields of DestinationString are
+ initialized to the length of the SourceString, which is zero if
+ SourceString is not specified.
+
+ This is a copy of the same function in \nt\private\ntos\rtl\string.c.
+ It is here to minimize what the linker drags into the image.
+
+Arguments:
+
+ DestinationString - Pointer to the counted string to initialize
+
+ SourceString - Optional pointer to a null terminated string that
+ the counted string is to point to.
+
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ DestinationString->Length = 0;
+ DestinationString->Buffer = (PCHAR)SourceString;
+ if (ARGUMENT_PRESENT( SourceString )) {
+ while (*SourceString++) {
+ DestinationString->Length++;
+ }
+
+ DestinationString->MaximumLength = (SHORT)(DestinationString->Length+1);
+ }
+ else {
+ DestinationString->MaximumLength = 0;
+ }
+}
+
+#endif
+
+#if (!defined FAILSAFE_BOOTER) && (!defined JNUPDATE)
+
+
+//
+// This stub is needed by some function in the rtl library.
+//
+
+NTSTATUS
+ZwQuerySystemInformation (
+ IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
+ OUT PVOID SystemInformation,
+ IN ULONG SystemInformationLength,
+ OUT PULONG ReturnLength OPTIONAL
+ )
+
+{
+ return;
+}
+
+#endif
+
+
+VOID
+FwErrorStackUnderflow (
+ IN ULONG Caller,
+ IN ULONG CallerOfTheCaller,
+ IN ULONG CallerRequestedStackArea
+ )
+
+/*++
+
+Routine Description:
+
+ A function was called that requested a stack area too large for
+ the current Firmware stack. The firmware _RtlCheckStack function
+ (see fwchkstk.s) calls this function to print out the fatal error
+ message.
+
+ The 64KB underneath the Firmware stack is used as a panic stack.
+
+Arguments:
+
+ Caller The address of the function that tried to
+ allocate the stack space.
+
+ CallerOfTheCaller The address of the function that called the
+ function held in "Caller".
+
+ CallerRequestedStackArea The amount of stack space requested by
+ "Caller".
+
+Return Value:
+
+ This never returns.
+
+--*/
+
+{
+ VenSetScreenColor(ArcColorRed, ArcColorWhite);
+ VenPrint(ST_STACK_UNDERFLOW_1_MSG);
+ VenPrint2(ST_STACK_UNDERFLOW_2_MSG, Caller, CallerOfTheCaller);
+ VenPrint2(ST_STACK_UNDERFLOW_3_MSG,
+ CallerRequestedStackArea,
+ FW_STACK_LOWER_BOUND);
+
+#if (!defined FAILSAFE_BOOTER) && (!defined JNUPDATE)
+
+ VenPrint(ST_HIT_KEY_FOR_MONITOR_MSG);
+ VenSetScreenColor(ArcColorWhite, ArcColorBlue);
+
+ FwWaitForKeypress(TRUE);
+
+ FwMonitor(0); // Should never return.
+
+#endif
+
+ while (TRUE) {
+ }
+}
+
+
+#ifndef JNUPDATE
+
+VOID
+KeFlushIoBuffers (
+ IN PMDL Mdl,
+ IN BOOLEAN ReadOperation,
+ IN BOOLEAN DmaOperation
+ )
+
+/*++
+
+Routine Description:
+
+ This function flushes the I/O buffer specified by the memory descriptor
+ list from the data cache on the current processor.
+
+Arguments:
+
+ Mdl - Supplies a pointer to a memory descriptor list that describes the
+ I/O buffer location.
+
+ ReadOperation - Supplies a boolean value that describes whether the I/O
+ operation is a read into memory.
+
+ DmaOperation - Supplies a boolean value that describes whether the I/O
+ operation is a DMA operation.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // temptemp
+ //
+ // This function must distribute the flush in an MP system.
+ //
+
+ HalFlushIoBuffers( Mdl, ReadOperation, DmaOperation );
+ return;
+}
+
+#endif
diff --git a/private/ntos/fw/alpha/tools/fwimagen/fwimagen.c b/private/ntos/fw/alpha/tools/fwimagen/fwimagen.c
new file mode 100644
index 000000000..3d62d90dd
--- /dev/null
+++ b/private/ntos/fw/alpha/tools/fwimagen/fwimagen.c
@@ -0,0 +1,135 @@
+/*
+ * fwimagen.c
+ *
+ * program to build a netloadable firmware image
+ *
+ *
+ * inputs:
+ *
+ * pal - stripped object file for pal code
+ * firmware - stripped image file for firmware
+ * image - output file name
+ *
+ */
+
+
+/*
+ * output format
+ *
+ * 0000 0000 - 0000 3fff firmware pal code
+ * 0000 4000 - upwards firmware code + data
+ */
+
+
+/*
+ * must figure out where data segment sits, can we control it with
+ * a loader switch?
+ */
+
+#include <stdio.h>
+#include <io.h>
+#include <fcntl.h>
+
+#define PAL_SIZ 0x4000
+
+
+//
+// format: argv[0] palname firmware output
+//
+
+main( argc, argv )
+int argc;
+char **argv;
+{
+ FILE *fdpal, *fdfirm, *fdimage;
+ int inbytes=0, palbytes, ldrbytes, kernbytes, in, out;
+ unsigned char zero = 0;
+ unsigned char data;
+
+
+ if( argc != 4 ){
+ fprintf( stderr, "usage: %s pal firmware output\n", argv[0] );
+ exit(0);
+ }
+
+
+ if( (fdpal = fopen( argv[1], "rb" )) == NULL ){
+ fprintf( stderr, "error opening %s\n", argv[1] );
+ exit(0);
+ }
+
+ if( (fdfirm = fopen( argv[2], "rb" )) == NULL ){
+ fprintf( stderr, "error opening %s\n", argv[2] );
+ exit(0);
+ }
+
+ if( (fdimage = fopen( argv[3], "wb" )) == NULL ){
+ fprintf( stderr, "error opening %s for output\n", argv[3] );
+ exit(0);
+ }
+
+
+ /* write out the pal code */
+
+ inbytes = 0;
+ fprintf( stdout, "writing palcode ....\t" );
+ while( (in = fread( &data, sizeof(data), 1, fdpal) == sizeof(data) )){
+ inbytes += in;
+ if( (out = fwrite( &data, sizeof(data), 1, fdimage)) != sizeof(data) ){
+ fprintf( stderr, "error writing pal to %s: line %d\n", argv[3], __LINE__ );
+ exit(0);
+ }
+ }
+
+ inbytes += in;
+
+ if (in != 0) {
+ if( (out = fwrite( &data, in, 1, fdimage)) != in ){
+ fprintf( stderr, "error writing pal to %s: line %d\n", argv[3], __LINE__ );
+ fprintf( stderr, "write was %d, wrote %d\n", in, out);
+ exit(0);
+ }
+ }
+
+ if( inbytes > PAL_SIZ ){
+ fprintf( stderr, "pal exceeded %d bytes = %d, aborting...\n",
+ PAL_SIZ, inbytes );
+ exit(0);
+ }
+ fprintf( stdout, "%6x %d bytes\n", inbytes, inbytes );
+ palbytes = inbytes;
+
+ fprintf( stdout, "padding palcode ....\t" );
+ /* pad output to PAL_SIZ bytes */
+ while( inbytes++ < (PAL_SIZ) )
+ if( (out = fwrite( &zero, 1, 1, fdimage)) != 1 ){
+ fprintf( stderr, "error padding after pal to %s\n", argv[3] );
+ exit(0);
+ }
+ fprintf( stdout, "%6x %d bytes\n", inbytes - palbytes -1, inbytes - palbytes -1 );
+
+
+ /* write the firmware into the output file */
+ fprintf( stdout, "writing firmware ....\t" );
+ inbytes = 0;
+ while( (in = fread( &data, sizeof(data), 1, fdfirm) == sizeof(data) )){
+ inbytes += in;
+ if( (out = fwrite( &data, sizeof(data), 1, fdimage)) != sizeof(data) ){
+ fprintf( stderr, "error writing firmware to %s\n", argv[3] );
+ exit(0);
+ }
+ }
+
+ inbytes += in;
+
+ if ( in != 0 ) {
+ if( (out = fwrite( &data, in, 1, fdimage)) != in ){
+ fprintf( stderr, "error writing firmwaer to %s\n", argv[3] );
+ exit(0);
+ }
+ }
+
+ fprintf( stdout, "%6x %d bytes\n", inbytes, inbytes );
+
+}
+
diff --git a/private/ntos/fw/alpha/tools/fwpack/fsbpack.c b/private/ntos/fw/alpha/tools/fwpack/fsbpack.c
new file mode 100644
index 000000000..647fb1610
--- /dev/null
+++ b/private/ntos/fw/alpha/tools/fwpack/fsbpack.c
@@ -0,0 +1,351 @@
+/*++
+
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ fwpack.c
+
+Abstract:
+
+ This module is the program that takes binary firmware image
+ (created by fwimagen.exe) and creates a packed firmware
+ update file for the JNUPDATE.EXE program.
+
+ The format of the update file is:
+
+ +------------------------------------------------+
+ | A zero-terminated string that identifies this |
+ | file. Must be < = 400 characters in length |
+ | and should print out in < = 10 screen rows. |
+ | Jnupdate gives this string to a printf. |
+ +------------------------------------------------+
+ | A single byte indicating which block to start |
+ | updating. (0 -- F) |
+ +------------------------------------------------+
+ | Binary data for the FlashFile ROM, starting |
+ | at the starting block, padded with 0's to an |
+ | even multiple of 64KB, with a production |
+ | ROL-and-ADD checksum in the last byte. |
+ | (The checksum will be ignored by a J0/AX02 |
+ | SROM.) |
+ +------------------------------------------------+
+ | A longword additive-zero checksum |
+ +------------------------------------------------+
+
+Notes:
+
+1. The ASCIZ identifying string will be printed out on the users's
+screen to identify the update. It is given to a printf. This should
+contain the name of the update, manufacturing date, copyright notice, etc.
+
+2. This program has the capability to package the binary data for the
+Carey McMaster J0/AX02 SROM, which requires a special header at the beginning
+of the firmware image.
+
+3. There are three checksums:
+ a) A rotate-and-add byte checksum is written out as the last byte in
+ the binary data section. The Ayr SROM and POST requires this.
+ b) If we are making a J0/AX02 file, a checksum is included in the
+ firmware image header.
+ c) The entire file is covered by an additive-zero checksum.
+
+
+Arguments:
+
+ argv[1] The ASCIZ identification string.
+
+ argv[2] The starting block number, in the range 0 -- F.
+
+ argv[3] The filespec of the firmware binary image. This
+ is the output of the fwimagen.exe program.
+
+ argv[4] The filespec of the output file. Convention:
+
+ jensfw.bin is a production update file.
+
+ jensfwj0.bin is a McMaster update file.
+
+ argv[5] If present, we product a binary file that is
+ compatible with the Carey McMaster J0 SROM.
+ (The value of this argument is not checked).
+
+Outputs:
+
+ The output file receives the packed firmware upgrade data.
+
+
+Author:
+
+ John DeRosa 21-October-1992
+
+
+Revision History:
+
+--*/
+
+#include <stdio.h>
+
+
+// Typedefs, and define truth
+typedef unsigned char UCHAR;
+typedef char CHAR;
+typedef long LONG;
+typedef unsigned long ULONG;
+typedef int BOOLEAN;
+typedef void VOID;
+typedef int INT;
+typedef char* PCHAR;
+
+#define FALSE 0
+#define TRUE 1
+
+
+// This is more convenient as a static variable.
+FILE *FirmwareOutFile;
+
+UCHAR
+RotateLeft (
+ UCHAR Data
+ )
+/*++
+
+ This returns the Data parameter barrel rotated left by 1.
+
+--*/
+{
+ return (((Data & 0x7f) << 1) + ((Data & 0x80) >> 7));
+}
+
+VOID
+WriteAByte (
+ UCHAR OutData
+ )
+/*++
+
+ Writes a byte to the output file, and exits if error.
+
+--*/
+{
+ if (((fwrite(&OutData, 1, 1, FirmwareOutFile)) != 1) ||
+ ferror(FirmwareOutFile)) {
+ fprintf(stderr, "?ERROR on output file.\n");
+ exit(0);
+ }
+}
+
+INT
+main (
+ INT argc,
+ PCHAR argv[]
+ )
+{
+ FILE *FirmwareInFile;
+ PCHAR Terminator;
+ UCHAR InputData;
+ UCHAR TempChar;
+ ULONG TempULong;
+ UCHAR ROMChecksum;
+ ULONG Checksum = 0;
+ LONG FileChecksum;
+ LONG Index;
+ BOOLEAN J0SROM = FALSE;
+
+
+ printf("fsb experimental pack v1.1x\n");
+
+ // Check for bad command line
+ if ((argc != 5) && (argc != 6)) {
+ printf("Usage: %s string decimal-starting-block infile outfile [J0SROM-flag]\n", argv[0] );
+ printf(" Use jensfw.bin for production output file.\n");
+ printf(" Use jensfwj0.bin for McMaster output file.\n");
+ exit(0);
+ }
+
+
+ // What kind of binary file are we to product?
+ if (argc == 6) {
+ J0SROM = TRUE; // make a McM J0SROM file...
+ }
+
+
+ // Open the firmware input binary file
+ printf("Opening %s for reading.\n", argv[3]);
+ if ((FirmwareInFile = fopen(argv[3], "rb")) == NULL ) {
+ fprintf(stderr, "Error opening %s\n", argv[3]);
+ exit(0);
+ }
+
+
+ // Open the output file
+ printf("Opening %s for writing.\n", argv[4]);
+ if ((FirmwareOutFile = fopen(argv[4], "wb")) == NULL ) {
+ fprintf(stderr, "Error opening %s\n", argv[4]);
+ exit(0);
+ }
+
+
+ printf("Writing the identification string.\n");
+ Index = 0;
+ do {
+ TempChar = *(argv[1]+Index);
+ Checksum += TempChar;
+ WriteAByte(TempChar);
+ Index++;
+ } while(*(argv[1]+Index-1) != 0); // Output string will be 0-terminated
+
+
+ printf("Writing the starting block number of %s.\n", argv[2]);
+ TempULong = strtoul(argv[2], &Terminator, 10);
+ TempChar = TempULong;
+ Checksum += TempChar;
+ WriteAByte(TempChar);
+
+ printf("Writing the firmware data...\n");
+
+ Index = 0;
+
+ //
+ // If this is a J0SROM -type file, we have to write the 16-byte header
+ // first. As this contains a checksum, we will read the input file
+ // and then reset it back to the beginning.
+ //
+
+ if (J0SROM) {
+ UCHAR InputData;
+ ULONG J0Checksum = 0;
+ ULONG Length = 0;
+ ULONG TempX;
+ ULONG TempY;
+ UCHAR J0Signatures[8] = {0xc3, 0xc3, 0x5a, 0x5a,
+ 0x3c, 0x3c, 0xa5, 0xa5};
+
+ printf("Writing the J0SROM header...\n");
+
+ Index += 16;
+
+ do {
+ fread(&InputData, 1, 1, FirmwareInFile);
+
+ if (ferror(FirmwareInFile)) {
+ fprintf(stderr, "?ERROR on input file.\n");
+ exit(0);
+ }
+
+ if (feof(FirmwareInFile) == 0) {
+ J0Checksum += InputData;
+ Length++;
+ }
+ } while(feof(FirmwareInFile) == 0);
+
+ //
+ // J0Checksum = the J0SROM-required checksum.
+ // Length = the number of bytes in the input file. Although
+ // we will pad the binary data in the output file to
+ // a multiple of 64KB, the padding is of course unused
+ // data, and so Length is what we will write to the
+ // header.
+ //
+
+ // Reset the input file to the beginning
+ if (fseek(FirmwareInFile, 0, SEEK_SET)) {
+ fprintf(stderr, "?ERROR resetting binary file to the beginning.\n");
+ exit(0);
+ }
+
+
+ // Write the J0SROM Checksum.
+ for (TempX = 0; TempX < 4; TempX++) {
+ InputData = J0Checksum & 0xff;
+ WriteAByte(InputData);
+ Checksum += InputData;
+ J0Checksum = J0Checksum >> 8;
+ }
+
+
+ // Write the first and second signatures.
+ for (TempX = 0; TempX < 8; TempX++) {
+ InputData = J0Signatures[TempX];
+ WriteAByte(InputData);
+ Checksum += InputData;
+ }
+
+
+ // Write the size of the firmware.
+ for (TempX = 0; TempX < 4; TempX++) {
+ InputData = Length & 0xff;
+ WriteAByte(InputData);
+ Checksum += InputData;
+ Length = Length >> 8;
+ }
+
+ } // if (J0SROM)
+
+
+ printf("Transferring input file to output file...\n");
+
+ ROMChecksum = 0;
+
+ do {
+ fread(&InputData, 1, 1, FirmwareInFile);
+
+ if (ferror(FirmwareInFile)) {
+ printf("?ERROR on input file, %d. bytes written.\n", Index);
+ exit(0);
+ }
+
+ if (feof(FirmwareInFile) == 0) {
+
+ // For the additive-zero checksum covering this file.
+ Checksum += InputData;
+
+ // For a production checksum in the ROM. Barrel-rotate and add.
+ ROMChecksum = RotateLeft(ROMChecksum) + InputData;
+
+ WriteAByte(InputData);
+ Index++;
+ }
+
+ } while(feof(FirmwareInFile) == 0);
+
+ // Index now contains the number of firmware binary data bytes that were
+ // written to the output file.
+ printf ("%d. firmware bytes written.\n", Index);
+
+
+ printf("Padding the binary data to an even multiple of 5 * 64kb.\n");
+
+ // Bump Index to account for our having to write the production
+ // checksum.
+ Index++;
+
+ TempULong = 0;
+ while ((Index % 0x50000) != 0) {
+ // "Add zero" to the the ROL running checksum.
+ ROMChecksum = RotateLeft(ROMChecksum);
+ WriteAByte(TempULong);
+ Index++;
+ }
+
+ // Now write the production checksum.
+ Checksum += ROMChecksum;
+ WriteAByte(ROMChecksum);
+
+ FileChecksum = 0 - Checksum;
+ printf ("Writing the checksum. Sum of all bytes = 0x%x, FileChecksum = 0x%x\n",
+ Checksum, FileChecksum);
+ if ((fwrite(&FileChecksum, sizeof(FileChecksum), 1, FirmwareOutFile)) != 1) {
+ fprintf(stderr, "?ERROR writing to output file.\n");
+ exit(0);
+ }
+
+ if (fclose(FirmwareOutFile) == EOF) {
+ fprintf(stderr, "?ERROR closing output file.\n");
+ exit(0);
+ }
+
+ fclose(FirmwareInFile);
+
+ exit(0);
+}
+
diff --git a/private/ntos/fw/alpha/tools/fwpack/fwpack.c b/private/ntos/fw/alpha/tools/fwpack/fwpack.c
new file mode 100644
index 000000000..6d5b7ecca
--- /dev/null
+++ b/private/ntos/fw/alpha/tools/fwpack/fwpack.c
@@ -0,0 +1,351 @@
+/*++
+
+Copyright (c) 1992, 1993 Digital Equipment Corporation
+
+Module Name:
+
+ fwpack.c
+
+Abstract:
+
+ This module is the program that takes binary firmware image
+ (created by fwimagen.exe) and creates a packed firmware
+ update file for the JNUPDATE.EXE program.
+
+ The format of the update file is:
+
+ +------------------------------------------------+
+ | A zero-terminated string that identifies this |
+ | file. Must be < = 400 characters in length |
+ | and should print out in < = 10 screen rows. |
+ | Jnupdate gives this string to a printf. |
+ +------------------------------------------------+
+ | A single byte indicating which block to start |
+ | updating. (0 -- F) |
+ +------------------------------------------------+
+ | Binary data for the FlashFile ROM, starting |
+ | at the starting block, padded with 0's to an |
+ | even multiple of 64KB, with a production |
+ | ROL-and-ADD checksum in the last byte. |
+ | (The checksum will be ignored by a J0/AX02 |
+ | SROM.) |
+ +------------------------------------------------+
+ | A longword additive-zero checksum |
+ +------------------------------------------------+
+
+Notes:
+
+1. The ASCIZ identifying string will be printed out on the users's
+screen to identify the update. It is given to a printf. This should
+contain the name of the update, manufacturing date, copyright notice, etc.
+
+2. This program has the capability to package the binary data for the
+Carey McMaster J0/AX02 SROM, which requires a special header at the beginning
+of the firmware image.
+
+3. There are three checksums:
+ a) A rotate-and-add byte checksum is written out as the last byte in
+ the binary data section. The Ayr SROM and POST requires this.
+ b) If we are making a J0/AX02 file, a checksum is included in the
+ firmware image header.
+ c) The entire file is covered by an additive-zero checksum.
+
+
+Arguments:
+
+ argv[1] The ASCIZ identification string.
+
+ argv[2] The starting block number, in the range 0 -- F.
+
+ argv[3] The filespec of the firmware binary image. This
+ is the output of the fwimagen.exe program.
+
+ argv[4] The filespec of the output file. Convention:
+
+ jensfw.bin is a production update file.
+
+ jensfwj0.bin is a McMaster update file.
+
+ argv[5] If present, we product a binary file that is
+ compatible with the Carey McMaster J0 SROM.
+ (The value of this argument is not checked).
+
+Outputs:
+
+ The output file receives the packed firmware upgrade data.
+
+
+Author:
+
+ John DeRosa 21-October-1992
+
+
+Revision History:
+
+--*/
+
+#include <stdio.h>
+
+
+// Typedefs, and define truth
+typedef unsigned char UCHAR;
+typedef char CHAR;
+typedef long LONG;
+typedef unsigned long ULONG;
+typedef int BOOLEAN;
+typedef void VOID;
+typedef int INT;
+typedef char* PCHAR;
+
+#define FALSE 0
+#define TRUE 1
+
+
+// This is more convenient as a static variable.
+FILE *FirmwareOutFile;
+
+UCHAR
+RotateLeft (
+ UCHAR Data
+ )
+/*++
+
+ This returns the Data parameter barrel rotated left by 1.
+
+--*/
+{
+ return (((Data & 0x7f) << 1) + ((Data & 0x80) >> 7));
+}
+
+VOID
+WriteAByte (
+ UCHAR OutData
+ )
+/*++
+
+ Writes a byte to the output file, and exits if error.
+
+--*/
+{
+ if (((fwrite(&OutData, 1, 1, FirmwareOutFile)) != 1) ||
+ ferror(FirmwareOutFile)) {
+ fprintf(stderr, "?ERROR on output file.\n");
+ exit(0);
+ }
+}
+
+INT
+main (
+ INT argc,
+ PCHAR argv[]
+ )
+{
+ FILE *FirmwareInFile;
+ PCHAR Terminator;
+ UCHAR InputData;
+ UCHAR TempChar;
+ ULONG TempULong;
+ UCHAR ROMChecksum;
+ ULONG Checksum = 0;
+ LONG FileChecksum;
+ LONG Index;
+ BOOLEAN J0SROM = FALSE;
+
+
+ printf("fwpack v1\n");
+
+ // Check for bad command line
+ if ((argc != 5) && (argc != 6)) {
+ printf("Usage: %s string decimal-starting-block infile outfile [J0SROM-flag]\n", argv[0] );
+ printf(" Use jensfw.bin for production output file.\n");
+ printf(" Use jensfwj0.bin for McMaster output file.\n");
+ exit(0);
+ }
+
+
+ // What kind of binary file are we to product?
+ if (argc == 6) {
+ J0SROM = TRUE; // make a McM J0SROM file...
+ }
+
+
+ // Open the firmware input binary file
+ printf("Opening %s for reading.\n", argv[3]);
+ if ((FirmwareInFile = fopen(argv[3], "rb")) == NULL ) {
+ fprintf(stderr, "Error opening %s\n", argv[3]);
+ exit(0);
+ }
+
+
+ // Open the output file
+ printf("Opening %s for writing.\n", argv[4]);
+ if ((FirmwareOutFile = fopen(argv[4], "wb")) == NULL ) {
+ fprintf(stderr, "Error opening %s\n", argv[4]);
+ exit(0);
+ }
+
+
+ printf("Writing the identification string.\n");
+ Index = 0;
+ do {
+ TempChar = *(argv[1]+Index);
+ Checksum += TempChar;
+ WriteAByte(TempChar);
+ Index++;
+ } while(*(argv[1]+Index-1) != 0); // Output string will be 0-terminated
+
+
+ printf("Writing the starting block number of %s.\n", argv[2]);
+ TempULong = strtoul(argv[2], &Terminator, 10);
+ TempChar = TempULong;
+ Checksum += TempChar;
+ WriteAByte(TempChar);
+
+ printf("Writing the firmware data...\n");
+
+ Index = 0;
+
+ //
+ // If this is a J0SROM -type file, we have to write the 16-byte header
+ // first. As this contains a checksum, we will read the input file
+ // and then reset it back to the beginning.
+ //
+
+ if (J0SROM) {
+ UCHAR InputData;
+ ULONG J0Checksum = 0;
+ ULONG Length = 0;
+ ULONG TempX;
+ ULONG TempY;
+ UCHAR J0Signatures[8] = {0xc3, 0xc3, 0x5a, 0x5a,
+ 0x3c, 0x3c, 0xa5, 0xa5};
+
+ printf("Writing the J0SROM header...\n");
+
+ Index += 16;
+
+ do {
+ fread(&InputData, 1, 1, FirmwareInFile);
+
+ if (ferror(FirmwareInFile)) {
+ fprintf(stderr, "?ERROR on input file.\n");
+ exit(0);
+ }
+
+ if (feof(FirmwareInFile) == 0) {
+ J0Checksum += InputData;
+ Length++;
+ }
+ } while(feof(FirmwareInFile) == 0);
+
+ //
+ // J0Checksum = the J0SROM-required checksum.
+ // Length = the number of bytes in the input file. Although
+ // we will pad the binary data in the output file to
+ // a multiple of 64KB, the padding is of course unused
+ // data, and so Length is what we will write to the
+ // header.
+ //
+
+ // Reset the input file to the beginning
+ if (fseek(FirmwareInFile, 0, SEEK_SET)) {
+ fprintf(stderr, "?ERROR resetting binary file to the beginning.\n");
+ exit(0);
+ }
+
+
+ // Write the J0SROM Checksum.
+ for (TempX = 0; TempX < 4; TempX++) {
+ InputData = J0Checksum & 0xff;
+ WriteAByte(InputData);
+ Checksum += InputData;
+ J0Checksum = J0Checksum >> 8;
+ }
+
+
+ // Write the first and second signatures.
+ for (TempX = 0; TempX < 8; TempX++) {
+ InputData = J0Signatures[TempX];
+ WriteAByte(InputData);
+ Checksum += InputData;
+ }
+
+
+ // Write the size of the firmware.
+ for (TempX = 0; TempX < 4; TempX++) {
+ InputData = Length & 0xff;
+ WriteAByte(InputData);
+ Checksum += InputData;
+ Length = Length >> 8;
+ }
+
+ } // if (J0SROM)
+
+
+ printf("Transferring input file to output file...\n");
+
+ ROMChecksum = 0;
+
+ do {
+ fread(&InputData, 1, 1, FirmwareInFile);
+
+ if (ferror(FirmwareInFile)) {
+ printf("?ERROR on input file, %d. bytes written.\n", Index);
+ exit(0);
+ }
+
+ if (feof(FirmwareInFile) == 0) {
+
+ // For the additive-zero checksum covering this file.
+ Checksum += InputData;
+
+ // For a production checksum in the ROM. Barrel-rotate and add.
+ ROMChecksum = RotateLeft(ROMChecksum) + InputData;
+
+ WriteAByte(InputData);
+ Index++;
+ }
+
+ } while(feof(FirmwareInFile) == 0);
+
+ // Index now contains the number of firmware binary data bytes that were
+ // written to the output file.
+ printf ("%d. firmware bytes written.\n", Index);
+
+
+ printf("Padding the binary data to an even multiple of 64kb.\n");
+
+ // Bump Index to account for our having to write the production
+ // checksum.
+ Index++;
+
+ TempULong = 0;
+ while ((Index % 0x10000) != 0) {
+ // "Add zero" to the the ROL running checksum.
+ ROMChecksum = RotateLeft(ROMChecksum);
+ WriteAByte(TempULong);
+ Index++;
+ }
+
+ // Now write the production checksum.
+ Checksum += ROMChecksum;
+ WriteAByte(ROMChecksum);
+
+ FileChecksum = 0 - Checksum;
+ printf ("Writing the checksum. Sum of all bytes = 0x%x, FileChecksum = 0x%x\n",
+ Checksum, FileChecksum);
+ if ((fwrite(&FileChecksum, sizeof(FileChecksum), 1, FirmwareOutFile)) != 1) {
+ fprintf(stderr, "?ERROR writing to output file.\n");
+ exit(0);
+ }
+
+ if (fclose(FirmwareOutFile) == EOF) {
+ fprintf(stderr, "?ERROR closing output file.\n");
+ exit(0);
+ }
+
+ fclose(FirmwareInFile);
+
+ exit(0);
+}
+
diff --git a/private/ntos/fw/alpha/xxstring.h b/private/ntos/fw/alpha/xxstring.h
new file mode 100644
index 000000000..99cd2efa0
--- /dev/null
+++ b/private/ntos/fw/alpha/xxstring.h
@@ -0,0 +1,53 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ xxstring.h
+
+Abstract:
+
+ This is the include file for language-independent, machine-specific
+ strings. See <machine>\alpha\xxstring.c for the string definitions.
+
+ These are filespec and ARC pathname strings. There is one of these
+ in each machine-specific subdirectory.
+
+Author:
+
+ John DeRosa and Ken Abramson 8-July-1993
+
+
+Revision History:
+
+
+--*/
+
+#include "ntos.h"
+
+extern PCHAR EISA_UNICODE_CONSOLE_OUT;
+extern PCHAR MULTI_UNICODE_CONSOLE_OUT;
+extern PCHAR EISA_NORMAL_CONSOLE_OUT;
+extern PCHAR MULTI_NORMAL_CONSOLE_OUT;
+extern PCHAR MULTI_UNICODE_KEYBOARD_IN;
+extern PCHAR MULTI_NORMAL_KEYBOARD_IN;
+
+extern PCHAR FW_KEYBOARD_IN_DEVICE;
+extern PCHAR FW_KEYBOARD_IN_DEVICE_PATH;
+extern PCHAR FW_CONSOLE_OUT_DEVICE;
+extern PCHAR FW_DISPLAY_DEVICE_PATH;
+extern PCHAR FW_FLOPPY_0_DEVICE;
+extern PCHAR FW_FLOPPY_0_FORMAT_DEVICE;
+extern PCHAR FW_FLOPPY_1_DEVICE;
+
+#ifdef EISA_PLATFORM
+extern PCHAR FW_ECU_LOCATION;
+#endif
+
+extern PCHAR FW_PRIMARY_FIRMWARE_UPDATE_TOOL;
+extern PCHAR FW_FIRMWARE_UPDATE_TOOL_NAME;
+extern PCHAR FW_FLOPPY_PARENT_NODE;
+extern PCHAR FW_FLOPPY_CDS_IDENTIFIER;
+extern PCHAR FW_SERIAL_0_DEVICE;
+extern PCHAR FW_SERIAL_1_DEVICE;