summaryrefslogtreecommitdiffstats
path: root/private/ntos/fw/alpha/fwio.c
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/fw/alpha/fwio.c
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ntos/fw/alpha/fwio.c')
-rw-r--r--private/ntos/fw/alpha/fwio.c1628
1 files changed, 1628 insertions, 0 deletions
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;
+}