From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- private/ntos/fw/alpha/arceisa.h | 547 ++++ private/ntos/fw/alpha/ati.h | 389 +++ private/ntos/fw/alpha/atidisk/68800.h | 362 +++ private/ntos/fw/alpha/atidisk/sample.txt | 131 + private/ntos/fw/alpha/bldrstub.c | 287 ++ private/ntos/fw/alpha/conftest.c | 1065 +++++++ private/ntos/fw/alpha/conftest.rsp | 11 + private/ntos/fw/alpha/debug.h | 7 + private/ntos/fw/alpha/eisafunc.c | 693 +++++ private/ntos/fw/alpha/eisaini.c | 3420 ++++++++++++++++++++ private/ntos/fw/alpha/eisamisc.c | 213 ++ private/ntos/fw/alpha/eisapod.c | 3694 ++++++++++++++++++++++ private/ntos/fw/alpha/eisastr.h | 39 + private/ntos/fw/alpha/eisausa.c | 102 + private/ntos/fw/alpha/fakebldr.c | 165 + private/ntos/fw/alpha/fakebldr.rsp | 10 + private/ntos/fw/alpha/fwcallbk.h | 279 ++ private/ntos/fw/alpha/fwchkstk.s | 136 + private/ntos/fw/alpha/fwhalt.c | 441 +++ private/ntos/fw/alpha/fwio.c | 1628 ++++++++++ private/ntos/fw/alpha/fwkd.c | 699 +++++ private/ntos/fw/alpha/fwload.c | 1035 +++++++ private/ntos/fw/alpha/fwmemdef.h | 101 + private/ntos/fw/alpha/fwp.h | 720 +++++ private/ntos/fw/alpha/fwpexcpt.h | 148 + private/ntos/fw/alpha/fwprint.c | 138 + private/ntos/fw/alpha/fwrstb.c | 172 + private/ntos/fw/alpha/fwsignal.c | 381 +++ private/ntos/fw/alpha/fwstring.h | 301 ++ private/ntos/fw/alpha/fwtime.c | 171 + private/ntos/fw/alpha/fwupusa.c | 168 + private/ntos/fw/alpha/fwusa.c | 470 +++ private/ntos/fw/alpha/inc.h | 908 ++++++ private/ntos/fw/alpha/iodevice.h | 258 ++ private/ntos/fw/alpha/jenassem.s | 579 ++++ private/ntos/fw/alpha/jenfonts.c | 961 ++++++ private/ntos/fw/alpha/jensen/alpha/aha174x.c | 2035 ++++++++++++ private/ntos/fw/alpha/jensen/alpha/chkstall.c | 142 + private/ntos/fw/alpha/jensen/alpha/jenstubs.c | 46 + private/ntos/fw/alpha/jensen/alpha/jnfs.c | 413 +++ private/ntos/fw/alpha/jensen/alpha/jnsetcfg.c | 1073 +++++++ private/ntos/fw/alpha/jensen/alpha/jxmemory.c | 817 +++++ private/ntos/fw/alpha/jensen/alpha/led.h | 36 + private/ntos/fw/alpha/jensen/alpha/machdef.h | 83 + private/ntos/fw/alpha/jensen/alpha/selftest.c | 599 ++++ private/ntos/fw/alpha/jensen/alpha/tbaqva.c | 413 +++ private/ntos/fw/alpha/jensen/alpha/version.c | 34 + private/ntos/fw/alpha/jensen/alpha/xxstring.c | 91 + private/ntos/fw/alpha/jensen/be_firm.cmd | 107 + private/ntos/fw/alpha/jensen/clean.cmd | 11 + private/ntos/fw/alpha/jensen/conftest.rsp | 10 + private/ntos/fw/alpha/jensen/fakebldr.rsp | 10 + private/ntos/fw/alpha/jensen/linkfsb.rsp | 48 + private/ntos/fw/alpha/jensen/linkjens.rsp | 67 + private/ntos/fw/alpha/jensen/linkupd.rsp | 21 + private/ntos/fw/alpha/jensen/makefile | 6 + private/ntos/fw/alpha/jensen/makefile.inc | 423 +++ private/ntos/fw/alpha/jensen/readmekd.txt | 68 + private/ntos/fw/alpha/jensen/sources | 220 ++ private/ntos/fw/alpha/jnfs.h | 84 + private/ntos/fw/alpha/jnfsfsb.h | 1 + private/ntos/fw/alpha/jnfsinit.c | 294 ++ private/ntos/fw/alpha/jnfsstb.c | 335 ++ private/ntos/fw/alpha/jnfsstub.s | 353 +++ private/ntos/fw/alpha/jnsetcom.c | 862 +++++ private/ntos/fw/alpha/jnsetenv.c | 408 +++ private/ntos/fw/alpha/jnsetmak.c | 2442 +++++++++++++++ private/ntos/fw/alpha/jnsetset.c | 1007 ++++++ private/ntos/fw/alpha/jnsettim.c | 421 +++ private/ntos/fw/alpha/jnsnprom.h | 222 ++ private/ntos/fw/alpha/jnsnvdeo.h | 206 ++ private/ntos/fw/alpha/jnupass.s | 181 ++ private/ntos/fw/alpha/jnupdate.c | 1450 +++++++++ private/ntos/fw/alpha/jnupdate.h | 1 + private/ntos/fw/alpha/jnupstub.c | 61 + private/ntos/fw/alpha/jnvendor.h | 57 + private/ntos/fw/alpha/jxboot.c | 2251 ++++++++++++++ private/ntos/fw/alpha/jxconfig.c | 1955 ++++++++++++ private/ntos/fw/alpha/jxdisp.c | 3460 +++++++++++++++++++++ private/ntos/fw/alpha/jxenvir.c | 1020 ++++++ private/ntos/fw/alpha/jxfboot.c | 2273 ++++++++++++++ private/ntos/fw/alpha/jxfwhal.h | 109 + private/ntos/fw/alpha/jxhwsup.c | 1936 ++++++++++++ private/ntos/fw/alpha/jxkbd.c | 581 ++++ private/ntos/fw/alpha/jxreboot.c | 157 + private/ntos/fw/alpha/jxserial.c | 590 ++++ private/ntos/fw/alpha/jxsysid.c | 168 + private/ntos/fw/alpha/jxvendor.c | 750 +++++ private/ntos/fw/alpha/kbdmouse.h | 164 + private/ntos/fw/alpha/kbdtest.c | 414 +++ private/ntos/fw/alpha/kdstubs.c | 201 ++ private/ntos/fw/alpha/monitor.c | 1785 +++++++++++ private/ntos/fw/alpha/monitor.h | 214 ++ private/ntos/fw/alpha/oli2msft.h | 39 + private/ntos/fw/alpha/omf.c | 3794 +++++++++++++++++++++++ private/ntos/fw/alpha/pal/checked/a221064.pal | Bin 0 -> 35328 bytes private/ntos/fw/alpha/pal/checked/a221066.pal | Bin 0 -> 27136 bytes private/ntos/fw/alpha/pal/checked/a221164.pal | Bin 0 -> 33280 bytes private/ntos/fw/alpha/pal/checked/a321064.pal | Bin 0 -> 27648 bytes private/ntos/fw/alpha/pal/free/a221064.pal | Bin 0 -> 32768 bytes private/ntos/fw/alpha/pal/free/a221066.pal | Bin 0 -> 25088 bytes private/ntos/fw/alpha/pal/free/a221164.pal | Bin 0 -> 31744 bytes private/ntos/fw/alpha/pal/free/a321064.pal | Bin 0 -> 25600 bytes private/ntos/fw/alpha/readme.txt | 11 + private/ntos/fw/alpha/rom.c | 1079 +++++++ private/ntos/fw/alpha/rom.h | 182 ++ private/ntos/fw/alpha/selfmap.h | 439 +++ private/ntos/fw/alpha/selftest.h | 119 + private/ntos/fw/alpha/stubs.c | 376 +++ private/ntos/fw/alpha/tools/fwimagen/fwimagen.c | 135 + private/ntos/fw/alpha/tools/fwpack/fsbpack.c | 351 +++ private/ntos/fw/alpha/tools/fwpack/fwpack.c | 351 +++ private/ntos/fw/alpha/xxstring.h | 53 + 113 files changed, 60944 insertions(+) create mode 100644 private/ntos/fw/alpha/arceisa.h create mode 100644 private/ntos/fw/alpha/ati.h create mode 100644 private/ntos/fw/alpha/atidisk/68800.h create mode 100644 private/ntos/fw/alpha/atidisk/sample.txt create mode 100644 private/ntos/fw/alpha/bldrstub.c create mode 100644 private/ntos/fw/alpha/conftest.c create mode 100644 private/ntos/fw/alpha/conftest.rsp create mode 100644 private/ntos/fw/alpha/debug.h create mode 100644 private/ntos/fw/alpha/eisafunc.c create mode 100644 private/ntos/fw/alpha/eisaini.c create mode 100644 private/ntos/fw/alpha/eisamisc.c create mode 100644 private/ntos/fw/alpha/eisapod.c create mode 100644 private/ntos/fw/alpha/eisastr.h create mode 100644 private/ntos/fw/alpha/eisausa.c create mode 100644 private/ntos/fw/alpha/fakebldr.c create mode 100644 private/ntos/fw/alpha/fakebldr.rsp create mode 100644 private/ntos/fw/alpha/fwcallbk.h create mode 100644 private/ntos/fw/alpha/fwchkstk.s create mode 100644 private/ntos/fw/alpha/fwhalt.c create mode 100644 private/ntos/fw/alpha/fwio.c create mode 100644 private/ntos/fw/alpha/fwkd.c create mode 100644 private/ntos/fw/alpha/fwload.c create mode 100644 private/ntos/fw/alpha/fwmemdef.h create mode 100644 private/ntos/fw/alpha/fwp.h create mode 100644 private/ntos/fw/alpha/fwpexcpt.h create mode 100644 private/ntos/fw/alpha/fwprint.c create mode 100644 private/ntos/fw/alpha/fwrstb.c create mode 100644 private/ntos/fw/alpha/fwsignal.c create mode 100644 private/ntos/fw/alpha/fwstring.h create mode 100644 private/ntos/fw/alpha/fwtime.c create mode 100644 private/ntos/fw/alpha/fwupusa.c create mode 100644 private/ntos/fw/alpha/fwusa.c create mode 100644 private/ntos/fw/alpha/inc.h create mode 100644 private/ntos/fw/alpha/iodevice.h create mode 100644 private/ntos/fw/alpha/jenassem.s create mode 100644 private/ntos/fw/alpha/jenfonts.c create mode 100644 private/ntos/fw/alpha/jensen/alpha/aha174x.c create mode 100644 private/ntos/fw/alpha/jensen/alpha/chkstall.c create mode 100644 private/ntos/fw/alpha/jensen/alpha/jenstubs.c create mode 100644 private/ntos/fw/alpha/jensen/alpha/jnfs.c create mode 100644 private/ntos/fw/alpha/jensen/alpha/jnsetcfg.c create mode 100644 private/ntos/fw/alpha/jensen/alpha/jxmemory.c create mode 100644 private/ntos/fw/alpha/jensen/alpha/led.h create mode 100644 private/ntos/fw/alpha/jensen/alpha/machdef.h create mode 100644 private/ntos/fw/alpha/jensen/alpha/selftest.c create mode 100644 private/ntos/fw/alpha/jensen/alpha/tbaqva.c create mode 100644 private/ntos/fw/alpha/jensen/alpha/version.c create mode 100644 private/ntos/fw/alpha/jensen/alpha/xxstring.c create mode 100644 private/ntos/fw/alpha/jensen/be_firm.cmd create mode 100644 private/ntos/fw/alpha/jensen/clean.cmd create mode 100644 private/ntos/fw/alpha/jensen/conftest.rsp create mode 100644 private/ntos/fw/alpha/jensen/fakebldr.rsp create mode 100644 private/ntos/fw/alpha/jensen/linkfsb.rsp create mode 100644 private/ntos/fw/alpha/jensen/linkjens.rsp create mode 100644 private/ntos/fw/alpha/jensen/linkupd.rsp create mode 100644 private/ntos/fw/alpha/jensen/makefile create mode 100644 private/ntos/fw/alpha/jensen/makefile.inc create mode 100644 private/ntos/fw/alpha/jensen/readmekd.txt create mode 100644 private/ntos/fw/alpha/jensen/sources create mode 100644 private/ntos/fw/alpha/jnfs.h create mode 100644 private/ntos/fw/alpha/jnfsfsb.h create mode 100644 private/ntos/fw/alpha/jnfsinit.c create mode 100644 private/ntos/fw/alpha/jnfsstb.c create mode 100644 private/ntos/fw/alpha/jnfsstub.s create mode 100644 private/ntos/fw/alpha/jnsetcom.c create mode 100644 private/ntos/fw/alpha/jnsetenv.c create mode 100644 private/ntos/fw/alpha/jnsetmak.c create mode 100644 private/ntos/fw/alpha/jnsetset.c create mode 100644 private/ntos/fw/alpha/jnsettim.c create mode 100644 private/ntos/fw/alpha/jnsnprom.h create mode 100644 private/ntos/fw/alpha/jnsnvdeo.h create mode 100644 private/ntos/fw/alpha/jnupass.s create mode 100644 private/ntos/fw/alpha/jnupdate.c create mode 100644 private/ntos/fw/alpha/jnupdate.h create mode 100644 private/ntos/fw/alpha/jnupstub.c create mode 100644 private/ntos/fw/alpha/jnvendor.h create mode 100644 private/ntos/fw/alpha/jxboot.c create mode 100644 private/ntos/fw/alpha/jxconfig.c create mode 100644 private/ntos/fw/alpha/jxdisp.c create mode 100644 private/ntos/fw/alpha/jxenvir.c create mode 100644 private/ntos/fw/alpha/jxfboot.c create mode 100644 private/ntos/fw/alpha/jxfwhal.h create mode 100644 private/ntos/fw/alpha/jxhwsup.c create mode 100644 private/ntos/fw/alpha/jxkbd.c create mode 100644 private/ntos/fw/alpha/jxreboot.c create mode 100644 private/ntos/fw/alpha/jxserial.c create mode 100644 private/ntos/fw/alpha/jxsysid.c create mode 100644 private/ntos/fw/alpha/jxvendor.c create mode 100644 private/ntos/fw/alpha/kbdmouse.h create mode 100644 private/ntos/fw/alpha/kbdtest.c create mode 100644 private/ntos/fw/alpha/kdstubs.c create mode 100644 private/ntos/fw/alpha/monitor.c create mode 100644 private/ntos/fw/alpha/monitor.h create mode 100644 private/ntos/fw/alpha/oli2msft.h create mode 100644 private/ntos/fw/alpha/omf.c create mode 100644 private/ntos/fw/alpha/pal/checked/a221064.pal create mode 100644 private/ntos/fw/alpha/pal/checked/a221066.pal create mode 100644 private/ntos/fw/alpha/pal/checked/a221164.pal create mode 100644 private/ntos/fw/alpha/pal/checked/a321064.pal create mode 100644 private/ntos/fw/alpha/pal/free/a221064.pal create mode 100644 private/ntos/fw/alpha/pal/free/a221066.pal create mode 100644 private/ntos/fw/alpha/pal/free/a221164.pal create mode 100644 private/ntos/fw/alpha/pal/free/a321064.pal create mode 100644 private/ntos/fw/alpha/readme.txt create mode 100644 private/ntos/fw/alpha/rom.c create mode 100644 private/ntos/fw/alpha/rom.h create mode 100644 private/ntos/fw/alpha/selfmap.h create mode 100644 private/ntos/fw/alpha/selftest.h create mode 100644 private/ntos/fw/alpha/stubs.c create mode 100644 private/ntos/fw/alpha/tools/fwimagen/fwimagen.c create mode 100644 private/ntos/fw/alpha/tools/fwpack/fsbpack.c create mode 100644 private/ntos/fw/alpha/tools/fwpack/fwpack.c create mode 100644 private/ntos/fw/alpha/xxstring.h (limited to 'private/ntos/fw/alpha') 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< (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; SlotNumberKey!=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<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<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<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<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)> 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) { + 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)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)= 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, 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 +#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< +//#include + +#include "machdef.h" +#include +#include // 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, + 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; iAdapterInterfaceType, + 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- + 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- + 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 +#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 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 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< 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 16) { + LineLength = 16; + } + for (i=0;iDevicePath != 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 component of +// the Path argument on the EISA bus spcified by the key of +// the 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: +// +// "V".LF"R" +// +// = 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: + // "V".LF"R" + // + // = 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<= (1 << WORD_2P2) ) + { + *((PULONG)( (PUCHAR)Buffer + *Count ))= + READ_PORT_ULONG( POmfHeaderContext->RomRead ); + *Count += 1<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 of the is optional. The caller can +// make the following assumptions if the is not +// included in the : +// . the firmware searches for folders whose type is MIPS first. +// This is equivalent to using '.A' as the . 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 . 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 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<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) + || + CheckedVersionVersion = 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<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<>> 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< OMF_MAX_FILE_LINK + || + OmfFileLength > OMF_MAX_FILE_LEN + || + OmfFileLink + OmfFileLength > OmfLength + || + FwFileIdChecksum( DeviceId, + RtlConvertUlongToLargeInteger(OmfFileLink<>> 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 Binary files /dev/null and b/private/ntos/fw/alpha/pal/checked/a221064.pal 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 Binary files /dev/null and b/private/ntos/fw/alpha/pal/checked/a221066.pal 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 Binary files /dev/null and b/private/ntos/fw/alpha/pal/checked/a221164.pal 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 Binary files /dev/null and b/private/ntos/fw/alpha/pal/checked/a321064.pal 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 Binary files /dev/null and b/private/ntos/fw/alpha/pal/free/a221064.pal 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 Binary files /dev/null and b/private/ntos/fw/alpha/pal/free/a221066.pal 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 Binary files /dev/null and b/private/ntos/fw/alpha/pal/free/a221164.pal 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 Binary files /dev/null and b/private/ntos/fw/alpha/pal/free/a321064.pal 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 +#include +#include + +#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 + + +// 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 + + +// 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 \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; -- cgit v1.2.3