/* * * Copyright (c) 1995 FirePower Systems, Inc. * Copyright (c) 1994 FirePower Systems Inc. * Copyright (c) 1994 FirmWorks, Mountain View CA USA. All rights reserved. * * $RCSfile: vrio.c $ * $Revision: 1.9 $ * $Date: 1996/04/15 02:55:53 $ * $Locker: $ * * * Module Name: * vrio.c * * Author: * Shin Iwamoto at FirePower Systems Inc. * * History: * 26-Sep-94 Shin Iwamoto at FirePower Systems Inc. * Added checking SeekMode in VrSeek(). * 15-Sep-94 Shin Iwamoto at FirePower Systems Inc. * Added saving the area pointed to by OpenPath in VrOpen(). * 15-Jul-94 Shin Iwamoto at FirePower Systems Inc. * Added for XXX_SEEK_IS_BUSTED in VrSeek(). * 14-Jul-94 Shin Iwamoto at FirePower Systems Inc. * Added ONE_IO_SIZE in VrRead() and VrWrite(). * 13-Jul-94 Shin Iwamoto at FirePower Systems Inc. * Added ENOSPC checking in VrWrite(). * Added for reading ahead in VrGetReadStatus() and VrRead(). * 11-Jul-94 Shin Iwamoto at FirePower Systems Inc. * Added some debugging facilities in VrOpen. These were * from checked-in veneer source code. * 16-Jun-94 Shin Iwamoto at FirePower Systems Inc. * Added when a serial device doesn't read in VrRead(). * 15-Jun-94 Shin Iwamoto at FirePower Systems Inc. * When OpenPath inclues console, the path is for a device. * So, FilePath was set to null. * 13-Jun-94 Shin Iwamoto at FirePower Systems Inc. * Added debugging statements. * Modified some porting from Mike Tooch at FirmWorks. * 18-May-94 Shin Iwamoto at FirePower Systems Inc. * Added for unsinged long size in VrWrite. * Added a part of VrMount. * Added that DirectoryFile flag is ignored in * VrSetFileInformation(). * Added for Delete flag in FileTable in * VrRead(), VrWrite(), VrSeek(), VrGetReadStatus() * Added some comments. * and VrSetFileInformation(). * 17-May-94 Shin Iwamoto at FirePower Systems Inc. * Added for NetworkDevice in GetDeviceAttribute(). * Added for unsinged long size in VrRead. * 12-May-94 Shin Iwamoto at FirePower Systems Inc. * Changed the name, strlen and strncmp to * VfStrlen and VfStrncmp. * 11-May-94 Shin Iwamoto at FirePower Systems Inc. * Added FIleTable. Changed rootnode to RootNode. * Put cast PCAHR to the first parameter of bzero. * Changed OFPhandle to OfPhandle. * Changed the name of VrFindCOnfigurationNode. * 10-May-94 Shin Iwamoto at FirePower Systems Inc. * Changed Vr{Open|Close|Read|Write|Seek} because of * changing the file table structure. * 05-May-94 Shin Iwamoto at FirePower Systems Inc. * Created. * */ #include "veneer.h" // // Some switches // #define MAX_OPEN_PATH_SIZE MAX_PATH_NAME_SIZE #define ONE_IO_SIZE 1024*1024 #define ZERO_LARGE 0 #define NOT_ZERO_LARGE 1 #define Minimum(X,Y) ((X) < (Y) ? (X) : (Y)) // // File Table definition // FILE_TABLE_ENTRY FileTable[FILE_TABLE_SIZE]; // // Function declarations // STATIC ARC_STATUS GetFileTableEntry( OUT PULONG ); STATIC ARC_STATUS GetDeviceAttribute( IN ULONG, IN PCONFIGURATION_NODE ); STATIC VOID AddLargeInt( PLARGE_INTEGER, PLARGE_INTEGER ); STATIC VOID MoveLargeInt( PLARGE_INTEGER, PLARGE_INTEGER ); STATIC LONG IsLarge( PLARGE_INTEGER ); STATIC VOID DecrementLarge( PLARGE_INTEGER ); /* * Name: VrOpen * * Description: * This function opens the file specified by OpenPath. * The pathname is translated into the devicename for Open Firmware, * then OFOpen is called with the devicename. * * Arguments: * OpenPath - ARC compliant pathname of the device/file to be opened. * OpenMode - Supplies the mode in which the file is opened. * FileId - Pointer to a variable that receives the fileid for * this pathname. * * Return Value: * If the file is successfully opened returns ESUCCESS otherwise * returns an unsuccessful status. * */ ARC_STATUS VrOpen( IN PCHAR OpenPath, IN OPEN_MODE OpenMode, OUT PULONG FileId ) { PCHAR FilePath, DevicePath, Partition, Console; ihandle IHandle; ARC_STATUS Status; PCONFIGURATION_NODE ConfNode; PCHAR pstr1; LONG DevSpecLen; debug(VRDBG_OPEN, "VrOpen: Entry - Path: %s Mode: %x\n", OpenPath, OpenMode); if (strlen(OpenPath) >= MAX_OPEN_PATH_SIZE) { debug(VRDBG_OPEN, "VrOpen: ENAMETOOLONG: '%s'\n", OpenPath); return ENAMETOOLONG; } // // Find Partition, Console and FilePath in OpenPath. // FilePath = NULL; Partition = NULL; Console = NULL; for (pstr1 = OpenPath; *pstr1; pstr1++) { if (strncmp(pstr1, "partition", 9) == 0) { Partition = pstr1; while (*pstr1++ != ')') { ; } FilePath = pstr1; break; } else if (strncmp(pstr1, "console", 7) == 0) { Console = pstr1; while (*pstr1++ != ')') { ; } if (*pstr1 != '\0') { return EINVAL; } FilePath = NULL; // Console is a device. break; } else if (*pstr1 == ')') { FilePath = pstr1+1; } } // // Did we eventually wind up with a FilePath after all? // if ((FilePath != NULL) && (strlen(FilePath) == 0)) { FilePath = NULL; } debug(VRDBG_OPEN, "VrOpen: Partition '%s' FilePath '%s'\n", Partition == NULL ? "NULL" : Partition, FilePath == NULL ? "NULL" : FilePath); // // Check open mode for a device. // if ((FilePath == NULL) && (OpenMode > ArcOpenReadWrite)) { debug(VRDBG_OPEN, "VrOpen: EINVAL: '%s'\n", OpenPath); return EINVAL; } // // Extract the device name from OpenPath. // ConfNode = ArcPathToNode(OpenPath); if (ConfNode == NULL) { debug(VRDBG_OPEN, "VrOpen: ENODEV: '%s'\n", OpenPath); return ENODEV; } // // Translate the device name into the device path for Open Firmware. // Add space for the partition and file components. // pstr1 = NodeToPath(ConfNode); DevSpecLen = strlen(pstr1) + 16; // Enough for a partition specifier. if (FilePath != NULL) { DevSpecLen += strlen(FilePath); } DevicePath = zalloc(DevSpecLen); strcpy(DevicePath, pstr1); free(pstr1); // // Get a free entry in the file table. // if (Status = GetFileTableEntry(FileId)) { debug(VRDBG_OPEN, "VrOpen: GetFileTableEntry returned %x\n", Status); return Status; } // // Set flags in the FileTable. // if (Status = GetDeviceAttribute(*FileId, ConfNode)) { debug(VRDBG_OPEN, "VrOpen: GetDeviceAttribute returned %x\n", Status); return Status; } if ((Partition == NULL) && (FilePath == NULL)) { // A device (not file) FileTable[*FileId].Flags.Device = 1; strcat(DevicePath, ":0"); } else { // A file (not a device) // // Convert the partition and the filename (if they exist) as follows: // // [partition(key1)][] // --> :[key1][,] // strcat(DevicePath, ":"); if (Partition != NULL) { FileTable[*FileId].Flags.Partition = (FilePath == NULL); pstr1 = Partition; while (*pstr1++ != '(') { ; } if (*pstr1 == ')') { strcat(DevicePath, "0"); } else { PCHAR pstr2; pstr2 = DevicePath + strlen(DevicePath); do { *pstr2++ = *pstr1++; } while (*pstr1 != ')'); *pstr2 = '\0'; } } if (FilePath != NULL) { strcat(DevicePath, ","); strcat(DevicePath, FilePath); } } // // Now we can open the device path (including the file path). // IHandle = OFOpen(DevicePath); debug(VRDBG_OPEN, "OFOpen: IHandle: %x\n", IHandle); FileTable[*FileId].PathName = DevicePath; // // Checking related to OpenMode. // switch (OpenMode) { case ArcCreateWriteOnly: case ArcCreateReadWrite: if (IHandle != 0) { (VOID)OFClose(IHandle); return EACCES; } break; default: if (IHandle == 0) { return EIO; } } FileTable[*FileId].Flags.Open = 1; FileTable[*FileId].IHandle = IHandle; debug(VRDBG_OPEN, "VrOpen: Exit - FileId: %d IHandle: %x\n", *FileId, IHandle); return ESUCCESS; } /* * Name: VrClose * * Description: * This function closes a file or a device if it is opened. * * Arguments: * FileId - Supplies the file table index. * * Return Value: * If the specified file is open, then a close is attempted via * OFClose and ESUCCESS is returned. Otherwise, return an unsuccessful * status. * */ ARC_STATUS VrClose( IN ULONG FileId ) { debug(VRDBG_OPEN, "VrClose: Entry - FileId: %d\n", FileId); if (FileId >= FILE_TABLE_SIZE) { return EBADF; } if (FileTable[FileId].Flags.Open != 1) { return EACCES; } // // Close the file. // (VOID)OFClose(FileTable[FileId].IHandle); // // Release the file table entry. // // FileTable[FileId].Flags.Open = 0; bzero((PCHAR)&FileTable[FileId], sizeof(FILE_TABLE_ENTRY)); free(FileTable[FileId].PathName); debug(VRDBG_OPEN, "VrClose: Exit\n"); return ESUCCESS; } /* * Name: VrRead * * Description: * This function reads data from the device of file specified by FileId * into the buffer pointed to by Buffer. * * Arguments: * FileId - Supplies the file table index. * Buffer - Supplies a pointer to the buffer that receives the read * data. * Length - Supplies the maximum number of bytes to be read. * If this field contains the value zero, then no bytes * are 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 retuned. Otherwise, return * an unsuccessful status. * */ STATIC CHAR consin_readahead = 0; ARC_STATUS VrRead( IN ULONG FileId, OUT PVOID Buffer, IN ULONG Length, OUT PULONG Count ) { LARGE_INTEGER LInteger; PCHAR buf = (PCHAR) Buffer; if (FileId == 0) { // stdin if (consin_readahead) { *buf = consin_readahead; consin_readahead = 0; *Count = 1; } else { if (ConsoleIn == 0) { (void) VrFindConsolePath("stdin"); } while (((LONG)*Count = OFRead(ConsoleIn, Buffer, Length)) <= 0){ ; } } return ESUCCESS; } debug(VRDBG_RDWR, "VrRead: Entry - FileId: %d Buf: %x len: %d\n", FileId, Buffer, Length); // // If Length is zero, return as if the function were successful. // if (Length == 0) { *Count = 0; return ESUCCESS; } if (FileId == 1) { return EBADF; } if (FileId >= FILE_TABLE_SIZE) { return EBADF; } if (!(FileTable[FileId].Flags.Open == 1 && FileTable[FileId].Flags.Read == 1)) { return EACCES; } if (FileTable[FileId].Flags.Delete == 1) { return EACCES; } #ifdef NO_UNSIGNED_LONG_IO // // Calls the read routine. // (LONG)*Count = OFRead(FileTable[FileId].IHandle, Buffer, Length); if ((LONG)*Count == -1) { return EIO; // XXXX } #else // NO_UNSIGNED_LONG_IO // // Initialize Counter. // *Count = 0; // // Checking read ahead buffer. If already read, the copy the buffer // into Buffer. // if (FileTable[FileId].ReadAheadCount != 0) { *Count = FileTable[FileId].ReadAheadCount; bcopy(FileTable[FileId].ReadAheadBuffer, Buffer, *Count); Buffer = (PCHAR)Buffer + *Count; Length -= *Count; FileTable[FileId].ReadAheadCount = 0; } // // Calls the read routine. // while (Length > 0) { LONG SingleReadSize; LONG ReadCount; SingleReadSize = Minimum(Length, ONE_IO_SIZE); ReadCount = OFRead(FileTable[FileId].IHandle, Buffer, SingleReadSize); if (ReadCount == -1) { LONG Status; // // If an error in the second or later read happes, // the offset must be put back using OFSeek. // In reading ahead, this is useful. // if (*Count != 0) { Status = OFSeek(FileTable[FileId].IHandle, FileTable[FileId].Position.HighPart, FileTable[FileId].Position.LowPart); // // Ignore Status. // } return EIO; // XXXX } // // Retry to read, when the device is serial and there is no data. // if ((ReadCount == -2) && (*Count == 0)) { continue; } // // Update the number of bytes read successfully. // *Count += ReadCount; // // If the device represented by FileId is a network device, // read one time. If not yet read, continue. // if (FileTable[FileId].Flags.NetworkDevice == 1) { if ((ReadCount == 0) && (*Count == 0)) { continue; } return ESUCCESS; } // // Find EOF, then break this loop. // if (ReadCount < SingleReadSize) { break; } // // Update the remaining length and the buffer to point to // the next position. // Length -= SingleReadSize; Buffer = (PCHAR)Buffer + SingleReadSize; } #endif // NO_UNSIGNED_LONG_IO // // Calculates the position of the file. // LInteger.HighPart = 0; LInteger.LowPart = *Count; AddLargeInt(&FileTable[FileId].Position, &LInteger); debug(VRDBG_RDWR, "VrRead: Exit ReadCount: %d\n", *Count); return ESUCCESS; } /* * Name: VrWrite * * Description: * This function writes data from memory starting from the buffer * pointed to by Buffer to the device specified by FileId. * Upon completion of a successful write, the byte offset for FileId * is updated; otherwise the byte offset is left unchanged. * * Arguments: * FileId - Supplies the file table index. * Buffer - Supplies a pointer to the buffer that contains * the write data. * Length - Supplies the number of bytes to be written. * Count - Supplies a pointer to a variable that contains * the number of bytes actually transfered. * * Return Value: * If the specified file is open for write, then a write is attempted * using OFWrite and a status is returned. Otherwise, return * an unsuccessful status. * */ ARC_STATUS VrWrite( IN ULONG FileId, IN PVOID Buffer, IN ULONG Length, OUT PULONG Count ) { LARGE_INTEGER LInteger; ARC_STATUS Status; if (FileId == 1) { // stdout *Count = OFWrite(ConsoleOut, Buffer, Length); return ESUCCESS; } debug(VRDBG_RDWR, "VrWrite: Entry - FileId: %d Buf: %x len: %d\n", FileId, Buffer, Length); // // If Length is zero, return as if the function were successful. // if (Length == 0) { *Count = 0; return ESUCCESS; } if (FileId == 0) { return EBADF; } if (FileId >= FILE_TABLE_SIZE) { return EBADF; } if (!(FileTable[FileId].Flags.Open == 1 && FileTable[FileId].Flags.Write == 1)) { return EACCES; } if (FileTable[FileId].Flags.Delete == 1) { return EACCES; } // // If Length bytes cannot be placed into a network packet, // return ENOSPC without sending the packet, placing the number of bytes // that could be written in Count. // if (FileTable[FileId].Flags.NetworkDevice == 1) { ULONG MaxFrameSize; MaxFrameSize = get_int_prop(OFFinddevice(FileTable[FileId].PathName), "max-frame-size"); if (Length > MaxFrameSize) { *Count = MaxFrameSize; return ENOSPC; } } #ifdef NO_UNSIGNED_LONG_IO // // Calls the write routine. // Status = ESUCCESS; (LONG)*Count = OFWrite(FileTable[FileId].IHandle, Buffer, Length); if ((LONG)*Count == -1) { return EIO; // XXXX } #else // NO_UNSIGNED_LONG_IO Status = ESUCCESS; *Count = 0; while (Length > 0) { LONG SingleWriteSize; LONG WriteCount; SingleWriteSize = Minimum(Length, ONE_IO_SIZE); WriteCount = OFWrite(FileTable[FileId].IHandle, Buffer, SingleWriteSize); if (WriteCount == -1) { LONG SeekStatus; // // If an error in the second or later read happens, // the offset must be put back using OFSeek. // if (*Count != 0) { SeekStatus = OFSeek(FileTable[FileId].IHandle, FileTable[FileId].Position.HighPart, FileTable[FileId].Position.LowPart); // // Ignore Status. // } return EIO; // XXXX } // // Update the number of bytes written successfully. // *Count += WriteCount; // // If the device represented by FileId is a network device, // write one time. If not yet written, continue. // if (FileTable[FileId].Flags.NetworkDevice == 1) { if (WriteCount == 0) { continue; } return ESUCCESS; } // // Find that the device is full. // if (WriteCount < SingleWriteSize) { Status = ENOSPC; break; } // // Update the remaining length and the buffer to point to // the next position. // Length -= SingleWriteSize; Buffer = (PCHAR)Buffer + SingleWriteSize; } #endif // NO_UNSIGNED_LONG_IO // // Calculates the position of the file. // LInteger.HighPart = 0; LInteger.LowPart = *Count; AddLargeInt(&FileTable[FileId].Position, &LInteger); if (FileId >= 2) { debug(VRDBG_RDWR, "VrWrite: Exit WrtCount: %d, Status: %d\n", *Count, Status); } return Status; } /* * Name: VrMount * * Description: * This function is used to load and unload media for devices that * support removale media. * * Arguments: * MountPath - Supplies a pointer to the variable that contains * the path of the device. * Operation - Supplies a indication whether the media is to be * loaded or unloaded. * * Return Value: * If the specified path is for device, then a mount is attempted * a status is returned. Otherwise, return an unsuccessful status. * */ ARC_STATUS VrMount( IN PCHAR MountPath, IN MOUNT_OPERATION Operation ) { PCONFIGURATION_NODE ConfNode; PCHAR FilePath, pstr1; debug(VRDBG_OPEN, "VrMount: Entry - MountPath: %s Operation: %d\n", MountPath, Operation); // // Check that the MountPath is a device. // FilePath = MountPath; for (pstr1 = MountPath; *pstr1; pstr1++) { if (strncmp(pstr1, "partition", 9) == 0) { return EINVAL; } else if (strncmp(pstr1, "console", 7) == 0) { return EINVAL; } else if (*pstr1 == ')') { FilePath = pstr1+1; } } if (FilePath == MountPath || FilePath[0] != '\0') { return EINVAL; } // // Find the configuration node using the MountPath. // ConfNode = ArcPathToNode(MountPath); if (ConfNode == NULL) { return ENOENT; } // // Check that the device is removable. // if (!(ConfNode->Component.Flags.Removable)) { return ENOENT; // XXXX } // // Translate the device name into the device path for Open Firmware. // // XXXX // How do I mount/unmount ? // If Operation is MountUnloadMedia for not mounted device, // return ENXIO; debug(VRDBG_OPEN, "VrMount: Exit\n"); return ESUCCESS; } /* * Name: VrSeek * * Description: * This function changes the byte offset associated with the device, * partition, or file specified by FileId. * * Arguments: * FileId - Supplies the file table index. * Offset - Supplies a poiner to a structure that contains * the offset value. * SeekMode - Supplies the type of positioning to be performed. * * 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. * */ ARC_STATUS VrSeek( IN ULONG FileId, IN PLARGE_INTEGER Offset, IN SEEK_MODE SeekMode ) { LONG Status; debug(VRDBG_RDWR, "VrSeek: Entry - FileId: %d Offset: %x.%x Mode: %x\n", FileId, Offset->HighPart, Offset->LowPart, SeekMode); if (FileId >= FILE_TABLE_SIZE) { return EBADF; } if (FileTable[FileId].Flags.Open != 1) { return EACCES; } if (FileTable[FileId].Flags.Delete == 1) { return EACCES; } if (!(SeekMode == SeekRelative || SeekMode == SeekAbsolute)) { return EINVAL; } // // If the specified device is Network, only set Offset into FileTable // because the Offset is interpreted to be a count of input to ignore. // The offset is cleared after reading the input packet. // if (FileTable[FileId].Flags.NetworkDevice == 1) { (VOID)MoveLargeInt(&FileTable[FileId].Position, Offset); return ESUCCESS; } // // Set the file position according to SeekMode. // if (SeekMode == SeekRelative) { (VOID)AddLargeInt(&FileTable[FileId].Position, Offset); } else { (VOID)MoveLargeInt(&FileTable[FileId].Position, Offset); } // // If FileId is for Network device, the input packets are ignored // according to Offset and then return with ESUCCESS. // if (FileTable[FileId].Flags.NetworkDevice == 1) { while (IsLarge(&FileTable[FileId].Position) == NOT_ZERO_LARGE) { LONG ReadSize; CHAR Buffer[4]; if ((ReadSize = OFRead(FileTable[FileId].IHandle, Buffer, 1)) == -1) { return EIO; } if (ReadSize == 0) { continue; } DecrementLarge(&FileTable[FileId].Position); } return ESUCCESS; } Status = OFSeek(FileTable[FileId].IHandle, FileTable[FileId].Position.HighPart, FileTable[FileId].Position.LowPart); if (Status == -1) { return EINVAL; // XXXX } debug(VRDBG_RDWR, "VrSeek: Exit\n"); return ESUCCESS; } /* * Name: VrGetDirectoryEntry * * Description: * This function reads directory entries from the system partition * directory file specified by FileId. * * Arguments: * FileId - Supplies the file table index. * Buffer - Supplies a pointer to a buffer for the entry data. * Length - Supplies the number of entries to retrieve. * Count - Supplies a pointeer to the number of entries read * into the buffer. * * Return Value: * If the specified file is open for read, then the read is attempted * and the status is returned. Otherwise, retrun an unsuccessful status. * */ ARC_STATUS VrGetDirectoryEntry( IN ULONG FileId, OUT PDIRECTORY_ENTRY Buffer, IN ULONG Length, OUT PULONG Count ) { debug(VRDBG_OPEN, "VrGetDirectoryEntry: Entry - FileId: %d Length: %d\n", FileId, Length); if (FileId >= FILE_TABLE_SIZE) { return EBADF; } if (FileTable[FileId].Flags.Device) { return ENOTDIR; } if (!(FileTable[FileId].Flags.Open == 1 && FileTable[FileId].Flags.Read == 1)) { return EBADF; } // XXXX // Get Director Entry if (FileID != directory) return ENOTDIR; debug(VRDBG_OPEN, "VrGetDirectoryEntry: Exit\n"); return ESUCCESS; } /* * Name: VrGetFileInformation * * Description: * This function retunrs an information structure about the specified * file or partition. * * Arguments: * FileId - Supplies the file table index. * FileInformation - Supplies a pointer to the location of the file * information data. * * Return Value: * If the specified file is open, then getting the file information is * attempted and the status is returned. Otherwise, retrun an unsuccessful * status. * */ ARC_STATUS VrGetFileInformation( IN ULONG FileId, OUT PFILE_INFORMATION pFI ) { PFILE_TABLE_ENTRY fte; ihandle ih; PCONFIGURATION_NODE node; ULONG size_thang[2]; debug(VRDBG_OPEN, "VrGetFileInformation: Entry - FileId: %d\n", FileId); if (FileId >= FILE_TABLE_SIZE) { debug(VRDBG_OPEN, "VrGetFileInformation: Exit EBADF\n"); return EBADF; } fte = &FileTable[FileId]; if (fte->Flags.Open != 1) { debug(VRDBG_OPEN, "VrGetFileInformation: Exit EACCES\n"); return EACCES; } if (fte->Flags.Device == 1) { debug(VRDBG_OPEN, "VrGetFileInformation: Exit EINVAL\n"); return EINVAL; } ih = fte->IHandle; node = InstanceToNode(ih); pFI->CurrentPosition = fte->Position; pFI->Type = node->Component.Type; (void) OFCallMethod(2, 2, size_thang, "size", ih); pFI->EndingAddress.HighPart = size_thang[0]; pFI->EndingAddress.LowPart = size_thang[1]; if (fte->Flags.Partition == 1) { (void) OFCallMethod( 1, 2, &(pFI->StartingAddress.HighPart), "offset-high", ih); (void) OFCallMethod( 1, 2, &(pFI->StartingAddress.LowPart), "offset-low", ih); AddLargeInt(&pFI->EndingAddress, &pFI->StartingAddress); pFI->FileName[0] = '\0'; pFI->FileNameLength = 0; } else { /* * It's a file. */ pFI->StartingAddress.HighPart = 0; pFI->StartingAddress.LowPart = 0; strcpy(pFI->FileName, fte->PathName); // XXX s.b. strncpy(&,&,32) pFI->FileNameLength = strlen(fte->PathName) + 1; } #ifdef XXX pFI->Attributes = // Get this from the firmware, somehow. #endif debug(VRDBG_OPEN, "VrGetFileInformation:\n"); debug(VRDBG_OPEN, "\tStarting %x.%x\n", pFI->StartingAddress.HighPart, pFI->StartingAddress.LowPart); debug(VRDBG_OPEN, "\tEnding %x.%x\n", pFI->EndingAddress.HighPart, pFI->EndingAddress.LowPart); debug(VRDBG_OPEN, "\tCurrent %x.%x\n", pFI->CurrentPosition.HighPart, pFI->CurrentPosition.LowPart); debug(VRDBG_OPEN, "\tType %d FileNameLength %d\n", pFI->Type, pFI->FileNameLength); debug(VRDBG_OPEN, "\tFileName '%s'\n", pFI->FileNameLength ? pFI->FileName : "NULL"); return ESUCCESS; } /* * Name: VrGetReadStatus * * Description: * This function determines if any bytes would be returned if a read * operation were performed on FileId. * * Arguments: * FileId - Supplies the file table index. * * Return Value: * If the specified file is open, then the getting read status is * attempted and the status is returned. Otherwise, retrun an unsuccessful * status. * */ ARC_STATUS VrGetReadStatus( IN ULONG FileId ) { LONG Count; if (FileId == 0) { // stdin if (consin_readahead != 0) { return (ESUCCESS); } if (ConsoleIn == 0) { (void) VrFindConsolePath("stdin"); } if (OFRead(ConsoleIn, &consin_readahead, 1) != 1) { return (EAGAIN); } return (ESUCCESS); } debug(VRDBG_RDWR, "VrGetReadStatus: Entry - FileId: %d\n", FileId); if (FileId >= FILE_TABLE_SIZE) { return EBADF; } if (!(FileTable[FileId].Flags.Open == 1 && FileTable[FileId].Flags.Read == 1)) { return EACCES; } if (FileTable[FileId].Flags.Delete == 1) { return EACCES; } // // Try to read one byte. // Count = OFRead(FileTable[FileId].IHandle, FileTable[FileId].ReadAheadBuffer, 1); if (Count != 1) { FileTable[FileId].ReadAheadCount = 0; // For safety. debug(VRDBG_RDWR, "VrGetReadStatus: Exit - with EAGAIN\n"); return EAGAIN; } // // Now read ahead one byte. // FileTable[FileId].ReadAheadCount = 1; if (FileId >= 2) { debug(VRDBG_RDWR, "VrGetReadStatus: Exit\n"); } return ESUCCESS; } /* * Name: VrSetFileInformation * * Description: * This function sets the file attributes for the specified FileId. * * Arguments: * FileId - Supplies the file table index. * AttributeFlags - Supplies the attributes to be set for the file. * AttributeMask - Supplies the attribute Mask. * * Return Value: * If the specified file is open, then the setting file information is * attempted and the status is returned. Otherwise, retrun an unsuccessful * status. * */ ARC_STATUS VrSetFileInformation( IN ULONG FileId, IN ULONG AttributeFlags, IN ULONG AttributeMask ) { debug(VRDBG_OPEN, "VrSetFileInformation: Entry - FileId: %d AttributeFlags: %x AttributeMask: %x\n", FileId, AttributeFlags, AttributeMask); if (FileId >= FILE_TABLE_SIZE) { return EBADF; } if (!(FileTable[FileId].Flags.Open == 1)) { return EACCES; } if (FileTable[FileId].Flags.Device == 1) { return EINVAL; } // // The attribute DirectoryFile is ignored for this function. // AttributeMask &= ~ArcDirectoryFile; // // A file is marked for deletion by setting the DeleteFile flag // in voth the AttributeFlags and AttributeMask parameters. // In this case, the file can be access only by Close(). // if ((AttributeMask & ArcDeleteFile) && (AttributeFlags & ArcDeleteFile)) { // // When the file is a derectroy which is not empty or a read-only file, // EACCESS is retuned. // // XXXX not empy check is needed // if (!(FileTable[FileId].Flags.Read == 1 && FileTable[FileId].Flags.Write == 0)) { return EACCES; } FileTable[FileId].Flags.Delete = 1; } // XXX return OFSetFileInformation(FileId, Buffer, Length, Count); debug(VRDBG_OPEN, "VrSetFileInformation: Exit\n"); return(ESUCCESS); } /* * Name: VrIoInitialize * * Description: * This function initializes the I/O entry points in the firmware * transfer vector and the file table. * * Arguments: * None. * * Return Value: * None. * */ VOID VrIoInitialize( VOID ) { ULONG Index; // // Initialize the I/O entry points in the firmware transfer vector. // debug(VRDBG_ENTRY, "VrIoInitialize BEGIN......\n"); (PARC_CLOSE_ROUTINE) SYSTEM_BLOCK->FirmwareVector[CloseRoutine] = VrClose; (PARC_MOUNT_ROUTINE) SYSTEM_BLOCK->FirmwareVector[MountRoutine] = VrMount; (PARC_OPEN_ROUTINE) SYSTEM_BLOCK->FirmwareVector[OpenRoutine] = VrOpen; (PARC_READ_ROUTINE) SYSTEM_BLOCK->FirmwareVector[ReadRoutine] = VrRead; (PARC_SEEK_ROUTINE) SYSTEM_BLOCK->FirmwareVector[SeekRoutine] = VrSeek; (PARC_WRITE_ROUTINE) SYSTEM_BLOCK->FirmwareVector[WriteRoutine] = VrWrite; (PARC_READ_STATUS_ROUTINE) SYSTEM_BLOCK->FirmwareVector[ReadStatusRoutine] = VrGetReadStatus; (PARC_GET_FILE_INFO_ROUTINE) SYSTEM_BLOCK->FirmwareVector[GetFileInformationRoutine] = VrGetFileInformation; (PARC_SET_FILE_INFO_ROUTINE) SYSTEM_BLOCK->FirmwareVector[SetFileInformationRoutine] = VrSetFileInformation; (PARC_GET_DIRECTORY_ENTRY_ROUTINE) SYSTEM_BLOCK->FirmwareVector[GetDirectoryEntryRoutine] = VrGetDirectoryEntry; // // Initialize the file table. // for (Index = 0; Index < FILE_TABLE_SIZE; Index++) { FileTable[Index].Flags.Open = 0; } debug(VRDBG_ENTRY, "VrIoInitialize ......END\n"); return; } /* * Name: GetFileTableEntry (internal) * * 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. * */ STATIC ARC_STATUS GetFileTableEntry( OUT PULONG Entry ) { ULONG Index; for (Index = 2; Index < FILE_TABLE_SIZE; Index++) { if (FileTable[Index].Flags.Open == 0) { #ifdef notdef FileTable[Index].Position.LowPart = 0; FileTable[Index].Position.HighPart = 0; #endif // notdef bzero((PCHAR)&FileTable[Index], sizeof(FILE_TABLE_ENTRY)); *Entry = Index; return ESUCCESS; } } return EMFILE; } /* * Name: GetDeviceAttribute (internal) * * Description: * This function sets the specified File Table entry to the attribute. * * Arguments: * FileId - Supplies the file table index. * ConfNode - Supplies a pointer to the Configuration Node. * * Return Value: * If the Configuration node is not peripheral, then return ENODEV. * Otherwise, returns ESUCCESS. * */ STATIC ARC_STATUS GetDeviceAttribute( IN ULONG FileId, IN PCONFIGURATION_NODE ConfNode ) { if (ConfNode->Component.Class != PeripheralClass) { warn("GetDeviceAttribute: node %s(%d) not PeripheralClass.\n", ConfNode->ComponentName, ConfNode->Component.Key); return ENODEV; } if (ConfNode->Component.Type == MonitorPeripheral) { FileTable[FileId].Flags.DisplayDevice = 1; } if (ConfNode->Component.Flags.Removable) { FileTable[FileId].Flags.RemovableDevice = 1; } if (ConfNode->Component.Type == NetworkPeripheral) { FileTable[FileId].Flags.NetworkDevice = 1; } if (ConfNode->Component.Flags.Input) { FileTable[FileId].Flags.Read = 1; } if (ConfNode->Component.Flags.Output && !(ConfNode->Component.Flags.ReadOnly)) { FileTable[FileId].Flags.Write = 1; } return ESUCCESS; } /* * Name: AddLargeInt (internal) * * Description: * This function adds a large integer into another large ingeger. * * Arguments: * Position - Supplies a pointer to a variable to be added. * Value - Supplies a pointer to a variable to add. * * Return Value: * None. * */ STATIC VOID AddLargeInt( PLARGE_INTEGER Position, PLARGE_INTEGER Value ) { if ((Position->LowPart += Value->LowPart) < Value->LowPart) { Position->HighPart++; } Position->HighPart += Value->HighPart; } /* * Name: DecrementLarge (internal) * * Description: * This function decrements a large integer. * * Arguments: * Position - Supplies a pointer to a variable to be decremented. * * Return Value: * None. * */ STATIC VOID DecrementLarge( PLARGE_INTEGER Position ) { ULONG ULong = Position->LowPart; Position->LowPart--; if (Position->LowPart > ULong) { Position->HighPart--; } } /* * Name: MoveLargeInt (internal) * * Description: * This function copies a large integer into another large ingeger. * * Arguments: * Position - Supplies a pointer to a variable to be copied. * Value - Supplies a pointer to a variable to copy. * * Return Value: * None. * */ STATIC VOID MoveLargeInt( PLARGE_INTEGER Position, PLARGE_INTEGER Value ) { Position->LowPart = Value->LowPart; Position->HighPart = Value->HighPart; } /* * Name: IsLarge (internal) * * Description: * This function determines whether a large integer contains zero. * * Arguments: * Position - Supplies a pointer to a variable to be checked. * * Return Value: * If the large integer is zero, then returns ZERO_LARGE. Otherwise, * returns NOT_ZERO_LARGE. * */ STATIC LONG IsLarge( PLARGE_INTEGER Position ) { if (Position->LowPart != 0) { return NOT_ZERO_LARGE; } if (Position->HighPart != 0) { return NOT_ZERO_LARGE; } return ZERO_LARGE; }