📄 stavfs.c
字号:
/****************************************************************************** File Name : stavfs.c Description : Core driver functions.*****************************************************************************//* Includes ---------------------------------------------------------------- */#include <stdlib.h>#include <stdio.h>#include <ctype.h>#include <string.h>#include <assert.h>#include "stddefs.h"#include "sttbx.h"#include "stavfs.h"#include "internal.h"#include "avdevice.h"#include "hal.h"#include "diskpart.h"#include "rwbuffer.h"#include "root.h"#include "partitio.h"#include "cat.h"#include "file.h"#include "dir.h"/* Private Types ----------------------------------------------------------- *//* Private Constants ------------------------------------------------------- */#define STAVFS_REVISION "1.0.0"/* Private Variables ------------------------------------------------------- */static stavfs_Device_t LocalDevice[4]; /* Multiple devices *//* For a quick fix make this global */static stavfs_HAL_t HALData[1]; /* Multiple hard disks *//* The current implementation only supports one hard disk */static BOOL InitialisedLock = FALSE;static semaphore_t GlobalDeviceLock; /* This locks access to the structures spaning the devices *//* Exported Variables -------------------------------------------------- *//* Private Macros ---------------------------------------------------------- *//* Private Function Prototypes --------------------------------------------- */static void InitialiseGlobalData (void);/* Functions --------------------------------------------------------------- *//******************************************************************************Function Name : STAVFS_GetRevision Description : Report the revision of this implementation of the driver. Parameters :******************************************************************************/ST_Revision_t STAVFS_GetRevision (){ return (STAVFS_REVISION);}/******************************************************************************Function Name : STAVFS_Close Description : Close down the disk volume, closing all files and freeing all allocated memory. Parameters :******************************************************************************/ST_ErrorCode_t STAVFS_Close (STAVFS_Handle_t Handle){ ST_ErrorCode_t Error = ST_NO_ERROR; stavfs_Device_t *Device_p = (stavfs_Device_t *) Handle; if ((Device_p < LocalDevice) || (LocalDevice+TABLE_LEN(LocalDevice) < Device_p) || !Device_p->DeviceActive || (Device_p->OpenHandles == 0)) { STTBX_Print (("Invalid handle\n")); Error = ST_ERROR_INVALID_HANDLE; } else { stavfs_RootSector_t RootSector; ST_ErrorCode_t Tmp; semaphore_wait (&(Device_p->DeviceLock)); /* Flush MCAT now to avoid thrashing, since no more allocation is going to take place. Leave error reporting to stavfs_CloseAllFilesOnDevice */ stavfs_FlushCat(Device_p); /* no point flushing directories early because they change as file closes */ /* Find all open file handles and close them */ stavfs_CloseAllFilesOnDevice (Device_p); /* Close the MCAT (shouldn't need to do any flushing) */ Tmp = stavfs_CloseCat(Device_p); if (Tmp != ST_NO_ERROR) { STTBX_Print (("Error closing cats\n")); Error = Tmp; } /* Close the root directory (shouldn't need to do any flushing) */ Tmp = stavfs_CloseRootDir(Device_p); if (Tmp != ST_NO_ERROR) { STTBX_Print (("Error closing directories\n")); Error = Tmp; } /* Now mark partition as closed, but also in error if things didn't flush fully */ if (ST_NO_ERROR != stavfs_ReadRootSector (Device_p, &RootSector)) { STTBX_Print (("Error reading the root sector\n")); Error = STAVFS_ERROR_UNREADABLE_DISK; } else { RootSector.StateFlags &= ~ROOT_PARTITION_FLAG_INUSE; if (Error != ST_NO_ERROR) { RootSector.StateFlags |= ROOT_PARTITION_FLAG_BAD; } if (ST_NO_ERROR != stavfs_WriteRootSector (Device_p, &RootSector)) { STTBX_Print (("Error writing the root sector\n")); Error = STAVFS_ERROR_UNWRITABLE_DISK; } } Device_p->OpenHandles--; semaphore_signal (&(Device_p->DeviceLock)); } return (Error);}/******************************************************************************Function Name : STAVFS_GetFreeDiskSpace Description : Report the available disk space on the given partition. Parameters :******************************************************************************/ST_ErrorCode_t STAVFS_GetFreeDiskSpace (STAVFS_Handle_t Handle, U64 * Size){ ST_ErrorCode_t Error = ST_NO_ERROR; stavfs_Device_t *Device_p = (stavfs_Device_t*)Handle; assert(NULL != Handle); assert(NULL != Device_p); if (ST_NO_ERROR != (Error = stavfs_ValidateDevice(Device_p))) { STTBX_Print (("Invalid Device\n")); Error = ST_ERROR_INVALID_HANDLE; } else if (Size == NULL) { Error = ST_ERROR_BAD_PARAMETER; } else { /* Lock the driver */ semaphore_wait(&(Device_p->DeviceLock)); Error = stavfs_GetNumFreeClusters(Device_p, Size); if (Error == ST_NO_ERROR) { /* Get the size in sectors */ INT_I64_MulLit(*Size, Device_p->ClusterSize, *Size); /* Get the size in bytes */ /* Multiply by sector size (512) */ I64_ShiftLeft(9, *Size); } else { /* Bad Cluster Count */ INT_I64_SetValue(0, 0, *Size); } /* Release the driver */ semaphore_signal(&(Device_p->DeviceLock)); } return (Error);}/******************************************************************************Function Name : STAVFS_Init Description : Initialise the driver. We only currently support one instance of the driver. Parameters :******************************************************************************/ST_ErrorCode_t STAVFS_Init (ST_DeviceName_t Name, STAVFS_InitParams_t * InitParams){ ST_ErrorCode_t Error = ST_NO_ERROR; stavfs_HAL_t *ThisHal = NULL; stavfs_DiskPartitionTable_t PartitionTable; int i; /* Perform basic initialisation and aquire the lock */ InitialiseGlobalData (); if ((Name == NULL) || (Name[0] == '\0') || /* zero length */ (strlen(Name) > sizeof(ST_DeviceName_t) - 1)) /* can't copy in full with zero termination */ { STTBX_Print (("Bad device name\n")); Error = ST_ERROR_BAD_PARAMETER; } else if (InitParams == NULL) { STTBX_Print (("NULL InitParams\n")); Error = ST_ERROR_BAD_PARAMETER; } else if (InitParams->Flags != 0) { /* Check the structure flags */ STTBX_Print (("Feature not supported\n")); Error = ST_ERROR_FEATURE_NOT_SUPPORTED; } else if (NULL == InitParams->MemoryPartition) { STTBX_Print (("Null Memory Partition\n")); Error = ST_ERROR_BAD_PARAMETER; } else if (InitParams->PartitionNumber > 3 || InitParams->PartitionNumber < 0) { /* Check the partition number */ STTBX_Print (("Bad partition number\n")); Error = ST_ERROR_BAD_PARAMETER; } /* Do we have this disk open */ if (Error == ST_NO_ERROR) { for (i = 0; (i < TABLE_LEN (HALData)); i++) { if (HALData[i].Initialised) { if ((HALData[i].Protocol == InitParams->Protocol) && (HALData[i].UnitNumber == InitParams->UnitNumber) && (0 == strncmp (HALData[i].ATAPIName, InitParams->ATAPIName, sizeof (HALData[i].ATAPIName))) && (0 == strncmp (HALData[i].EVTName, InitParams->EVTName, sizeof (HALData[i].EVTName)))) { ThisHal = HALData + i; break; } } } } /* Do we have this device open */ if ((Error == ST_NO_ERROR) && (NULL != ThisHal)) { for (i = 0; (i < TABLE_LEN (LocalDevice)); i++) { if ((LocalDevice[i].HALData == ThisHal) && (LocalDevice[i].Partition == InitParams->PartitionNumber)) { /* We have this disk and partition open */ STTBX_Print (("This disk and partition is already open\n")); Error = ST_ERROR_ALREADY_INITIALIZED; } } } /* Is the device name in use */ if ((Error == ST_NO_ERROR) && (NULL != ThisHal)) { for (i = 0; (i < TABLE_LEN (LocalDevice)); i++) { if (LocalDevice[i].DeviceActive && (0 == strncmp (LocalDevice[i].DeviceName, Name, sizeof (LocalDevice[i].DeviceName)))) { /* The name is in use */ STTBX_Print (("This device name is already in use\n")); Error = ST_ERROR_ALREADY_INITIALIZED; } } } /* Open the HAL Layer */ if ((Error == ST_NO_ERROR) && (NULL == ThisHal)) { for (i = 0; (i < TABLE_LEN (HALData)) && HALData[i].Initialised; i++) { /* All done in the FOR */ } if (i == TABLE_LEN (HALData)) { /* Out of space */ STTBX_Print (("No free handles\n")); Error = ST_ERROR_NO_FREE_HANDLES; } else { strncpy (HALData[i].EVTName, InitParams->EVTName, sizeof (HALData[i].EVTName)); strncpy (HALData[i].ATAPIName, InitParams->ATAPIName, sizeof (HALData[i].ATAPIName)); HALData[i].Protocol = InitParams->Protocol; HALData[i].UnitNumber = InitParams->UnitNumber; ThisHal = HALData + i; if (ST_NO_ERROR != (Error = stavfs_HalInit (ThisHal))) { STTBX_Print (("Error when opening the HAL layer\n")); } } } /* Open the Device */ if (Error == ST_NO_ERROR) { /* Find a free entry */ for (i = 0; (i < TABLE_LEN (LocalDevice)) && (LocalDevice[i].HALData != NULL); i++) { /* All done in the FOR */ } if (i == TABLE_LEN (LocalDevice)) { /* Out of space */ STTBX_Print (("No free device handles\n")); Error = ST_ERROR_NO_FREE_HANDLES; } else { /* Lock the driver */ semaphore_wait(&(LocalDevice[i].DeviceLock)); /* Set the device name */ strncpy (LocalDevice[i].DeviceName, Name, sizeof (LocalDevice[i].DeviceName)); LocalDevice[i].DeviceActive = TRUE; LocalDevice[i].MemoryPartition = InitParams->MemoryPartition; LocalDevice[i].OpenHandles = 0; LocalDevice[i].Partition = InitParams->PartitionNumber; LocalDevice[i].HALData = ThisHal; LocalDevice[i].RWCache = NULL; LocalDevice[i].RootDir = NULL; LocalDevice[i].MCat = NULL; /* Read the partition table from disk so we know where the root sector is */ if (ST_NO_ERROR != stavfs_ReadPartitionTable (&LocalDevice[i], &PartitionTable)) { STTBX_Print (("Error reading partition table\n")); Error = ST_ERROR_BAD_PARAMETER; } else { /* Set the root sector value */ I64_SetValue (PartitionTable.StartLBA, 0, LocalDevice[i].RootSectorLBA); } if (Error == ST_NO_ERROR) { /* Initialise the R/W Cache */ Error = stavfs_InitRWCache (LocalDevice + i); } if (Error != ST_NO_ERROR) { /* If we have had an error then clean up */ int j; if (LocalDevice[i].RWCache != NULL) { /* Clear the R/W Cache */ stavfs_TermRWCache (LocalDevice + i); } LocalDevice[i].HALData = NULL; /* Check if this leaves this HAL unused */ for (j = 0; (j < TABLE_LEN (LocalDevice)) && (LocalDevice[j].HALData != ThisHal); j++) { /* All done in the FOR */ } if (j == TABLE_LEN (LocalDevice)) { /* The HAL is not being used */ /* Close down the HAL Layer */ if (ST_NO_ERROR != stavfs_HalTerm (ThisHal)) { STTBX_Print (("Failed to close HAL device\n")); Error = STAVFS_ERROR_UNWRITABLE_DISK; } } } /* Release the driver */ semaphore_signal(&(LocalDevice[i].DeviceLock)); } } /* Release the lock */ semaphore_signal (&(GlobalDeviceLock)); return (Error);}/******************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -