From 75e87cf46a3899f76bae5c64e130cfc033562e9a Mon Sep 17 00:00:00 2001 From: John Hodge Date: Fri, 6 Nov 2009 18:29:56 +0800 Subject: [PATCH] Added IO Cache Library, Moved FDD Driver to Modules Tree, Fixed Doxygen commenting --- Kernel/Makefile | 7 +- Kernel/drv/iocache.c | 317 ++++++++++++++++++++++++++++++ Kernel/drv/vterm.c | 3 +- Kernel/include/fs_devfs.h | 18 +- Kernel/include/iocache.h | 120 +++++++++++ Kernel/include/tpl_drv_common.h | 24 ++- Kernel/include/tpl_drv_keyboard.h | 10 +- Kernel/include/tpl_drv_video.h | 52 +++-- Kernel/include/vfs.h | 160 ++++++++++++--- Makefile.cfg | 4 +- Modules/FDD/Makefile | 7 + {Kernel/drv => Modules/FDD}/fdd.c | 65 ++++-- Modules/Makefile.tpl | 2 +- 13 files changed, 719 insertions(+), 70 deletions(-) create mode 100644 Kernel/drv/iocache.c create mode 100644 Kernel/include/iocache.h create mode 100644 Modules/FDD/Makefile rename {Kernel/drv => Modules/FDD}/fdd.c (86%) diff --git a/Kernel/Makefile b/Kernel/Makefile index 5f155978..9bec8449 100644 --- a/Kernel/Makefile +++ b/Kernel/Makefile @@ -21,7 +21,7 @@ OBJ += binary.o bin/elf.o OBJ += vfs/main.o vfs/open.o vfs/acls.o vfs/dir.o vfs/io.o vfs/mount.o vfs/memfile.o vfs/nodecache.o OBJ += vfs/fs/root.o vfs/fs/devfs.o OBJ += $(addprefix vfs/fs/, $(addsuffix .o,$(FILESYSTEMS))) -OBJ += drv/fifo.o drv/dma.o drv/pci.o drv/kb.o drv/vga.o drv/vterm.o +OBJ += drv/fifo.o drv/dma.o drv/iocache.o drv/pci.o drv/kb.o drv/vga.o drv/vterm.o OBJ += $(addprefix drv/, $(addsuffix .o,$(DRIVERS))) OBJ := $(addsuffix .$(ARCH), $(OBJ)) MODS += $(addprefix ../Modules/, $(addsuffix .xo.$(ARCH),$(MODULES))) @@ -33,13 +33,16 @@ DEPFILES := $(DEPFILES:%.o.$(ARCH)=%.d.$(ARCH)) SRCFILES = $(OBJ:%.o.$(ARCH)=%.c) SRCFILES := $(SRCFILES:%.ao.$(ARCH)=%.asm) -.PHONY: all clean +.PHONY: all clean apidoc all: $(BIN) clean: @$(RM) $(BIN) $(OBJ) $(DEPFILES) +apidoc: + doxygen Doxyfile.api + $(BIN): $(OBJ) $(MODS) arch/$(ARCHDIR)/link.ld Makefile @echo --- LD -o $(BIN) @$(LD) $(LDFLAGS) -o $(BIN) $(OBJ) $(MODS) -Map ../Map.$(ARCH).txt diff --git a/Kernel/drv/iocache.c b/Kernel/drv/iocache.c new file mode 100644 index 00000000..8ea6929a --- /dev/null +++ b/Kernel/drv/iocache.c @@ -0,0 +1,317 @@ +/* + * Acess2 Kernel + * - IO Cache + * + * By thePowersGang (John Hodge) + */ +#include +#include + +// === TYPES === +typedef struct sIOCache_Ent tIOCache_Ent; + +// === STRUCTURES === +struct sIOCache_Ent +{ + tIOCache_Ent *Next; + Uint64 Num; + Sint64 LastAccess; + Sint64 LastWrite; + Uint8 Data[]; +}; + +struct sIOCache +{ + tIOCache *Next; + int SectorSize; + int Lock; + int Mode; + Uint32 ID; + tIOCache_WriteCallback Write; + int CacheSize; + int CacheUsed; + tIOCache_Ent *Entries; +}; + +// === GLOBALS === + int glIOCache_Caches; +tIOCache *gIOCache_Caches = NULL; + int giIOCache_NumCaches = 0; + +// === CODE === +/** + * \fn tIOCache *IOCache_Create( tIOCache_WriteCallback Write, Uint32 ID, int SectorSize, int CacheSize ) + * \brief Creates a new IO Cache + */ +tIOCache *IOCache_Create( tIOCache_WriteCallback Write, Uint32 ID, int SectorSize, int CacheSize ) +{ + tIOCache *ret = malloc( sizeof(tIOCache) ); + + // Sanity Check + if(!ret) return NULL; + + // Fill Structure + ret->SectorSize = SectorSize; + ret->Mode = IOCACHE_WRITEBACK; + ret->ID = ID; + ret->Write = Write; + ret->CacheSize = CacheSize; + ret->CacheUsed = 0; + ret->Entries = 0; + + // Append to list + LOCK( &glIOCache_Caches ); + ret->Next = gIOCache_Caches; + gIOCache_Caches = ret; + RELEASE( &glIOCache_Caches ); + + // Return + return ret; +} + +/** + * \fn int IOCache_Read( tIOCache *Cache, Uint64 Sector, void *Buffer ) + * \brief Read from a cached sector + */ +int IOCache_Read( tIOCache *Cache, Uint64 Sector, void *Buffer ) +{ + tIOCache_Ent *ent; + + // Sanity Check! + if(!Cache || !Buffer) + return -1; + + // Lock + LOCK( &Cache->Lock ); + if(Cache->CacheSize == 0) { + RELEASE( &Cache->Lock ); + return -1; + } + + // Search the list + for( ent = Cache->Entries; ent; ent = ent->Next ) + { + // Have we found what we are looking for? + if( ent->Num == Sector ) { + memcpy(Buffer, ent->Data, Cache->SectorSize); + ent->LastAccess = now(); + RELEASE( &Cache->Lock ); + return 1; + } + // It's a sorted list, so as soon as we go past `Sector` we know + // it's not there + if(ent->Num > Sector) break; + } + + RELEASE( &Cache->Lock ); + return 0; +} + +/** + * \fn int IOCache_Add( tIOCache *Cache, Uint64 Sector, void *Buffer ) + * \brief Cache a sector + */ +int IOCache_Add( tIOCache *Cache, Uint64 Sector, void *Buffer ) +{ + tIOCache_Ent *ent, *prev; + tIOCache_Ent *new; + tIOCache_Ent *oldest = NULL, *oldestPrev; + + // Sanity Check! + if(!Cache || !Buffer) + return -1; + + // Lock + LOCK( &Cache->Lock ); + if(Cache->CacheSize == 0) { + RELEASE( &Cache->Lock ); + return -1; + } + + // Search the list + prev = (tIOCache_Ent*)&Cache->Entries; + for( ent = Cache->Entries; ent; prev = ent, ent = ent->Next ) + { + // Is it already here? + if( ent->Num == Sector ) { + RELEASE( &Cache->Lock ); + return 0; + } + + // Check if we have found the oldest entry + if( !oldest || oldest->LastAccess > ent->LastAccess ) { + oldest = ent; + oldestPrev = prev; + } + + // Here we go! + if(ent->Num > Sector) + break; + } + + // Create the new entry + new = malloc( sizeof(tIOCache_Ent) + Cache->SectorSize ); + new->Next = ent; + new->Num = Sector; + new->LastAccess = now(); + new->LastWrite = 0; // Zero is special, it means unmodified + memcpy(new->Data, Buffer, Cache->SectorSize); + + // Have we reached the maximum cached entries? + if( Cache->CacheUsed == Cache->CacheSize ) + { + tIOCache_Ent *savedPrev = prev; + oldestPrev = (tIOCache_Ent*)&Cache->Entries; + // If so, search for the least recently accessed entry + for( ; ent; prev = ent, ent = ent->Next ) + { + // Check if we have found the oldest entry + if( !oldest || oldest->LastAccess > ent->LastAccess ) { + oldest = ent; + oldestPrev = prev; + } + } + // Remove from list, write back and free + oldestPrev->Next = oldest->Next; + if(oldest->LastWrite && Cache->Mode != IOCACHE_VIRTUAL) + Cache->Write(Cache->ID, oldest->Num, oldest->Data); + free(oldest); + + // Decrement the used count + Cache->CacheUsed --; + + // Restore `prev` + prev = savedPrev; + } + + // Append to list + prev->Next = new; + Cache->CacheUsed ++; + + // Release Spinlock + RELEASE( &Cache->Lock ); + + // Return success + return 1; +} + +/** + * \fn int IOCache_Write( tIOCache *Cache, Uint64 Sector, void *Buffer ) + * \brief Read from a cached sector + */ +int IOCache_Write( tIOCache *Cache, Uint64 Sector, void *Buffer ) +{ + tIOCache_Ent *ent; + + // Sanity Check! + if(!Cache || !Buffer) + return -1; + // Lock + LOCK( &Cache->Lock ); + if(Cache->CacheSize == 0) { + RELEASE( &Cache->Lock ); + return -1; + } + + // Search the list + for( ent = Cache->Entries; ent; ent = ent->Next ) + { + // Have we found what we are looking for? + if( ent->Num == Sector ) { + memcpy(ent->Data, Buffer, Cache->SectorSize); + ent->LastAccess = ent->LastWrite = now(); + + if(Cache->Mode == IOCACHE_WRITEBACK) { + Cache->Write(Cache->ID, Sector, Buffer); + ent->LastWrite = 0; + } + + RELEASE( &Cache->Lock ); + return 1; + } + // It's a sorted list, so as soon as we go past `Sector` we know + // it's not there + if(ent->Num > Sector) break; + } + + RELEASE( &Cache->Lock ); + return 0; +} + +/** + * \fn void IOCache_Flush( tIOCache *Cache ) + * \brief Flush a cache + */ +void IOCache_Flush( tIOCache *Cache ) +{ + tIOCache_Ent *ent; + + if( Cache->Mode == IOCACHE_VIRTUAL ) return; + + // Lock + LOCK( &Cache->Lock ); + if(Cache->CacheSize == 0) { + RELEASE( &Cache->Lock ); + return; + } + + // Write All + for( ent = Cache->Entries; ent; ent = ent->Next ) + { + Cache->Write(Cache->ID, ent->Num, ent->Data); + ent->LastWrite = 0; + } + + RELEASE( &Cache->Lock ); +} + +/** + * \fn void IOCache_Destroy( tIOCache *Cache ) + * \brief Destroy a cache + */ +void IOCache_Destroy( tIOCache *Cache ) +{ + tIOCache_Ent *ent, *prev = NULL; + + // Lock + LOCK( &Cache->Lock ); + if(Cache->CacheSize == 0) { + RELEASE( &Cache->Lock ); + return; + } + + // Free All + for(ent = Cache->Entries; + ent; + prev = ent, ent = ent->Next, free(prev) ) + { + if( Cache->Mode != IOCACHE_VIRTUAL ) + { + Cache->Write(Cache->ID, ent->Num, ent->Data); + ent->LastWrite = 0; + } + } + + Cache->CacheSize = 0; + + RELEASE( &Cache->Lock ); + + // Remove from list + LOCK( &glIOCache_Caches ); + { + tIOCache *ent; + tIOCache *prev = (tIOCache*)&gIOCache_Caches; + for(ent = gIOCache_Caches; + ent; + prev = ent, ent = ent->Next ) + { + if(ent == Cache) { + prev->Next = ent->Next; + break; + } + } + } + RELEASE( &glIOCache_Caches ); + + free(Cache); +} diff --git a/Kernel/drv/vterm.c b/Kernel/drv/vterm.c index afd53ffc..1dde000a 100644 --- a/Kernel/drv/vterm.c +++ b/Kernel/drv/vterm.c @@ -24,6 +24,7 @@ #define DEFAULT_COLOUR (VT_COL_BLACK|(0xAAA<<16)) #define VT_FLAG_HIDECSR 0x01 +#define VT_FLAG_HASFB 0x10 //!< Set if the VTerm has requested the Framebuffer enum eVT_InModes { VT_INMODE_TEXT8, // UTF-8 Text Mode (VT100 Emulation) @@ -184,7 +185,7 @@ int VT_Install(char **Arguments) DevFS_AddDevice( &gVT_DrvInfo ); // Set kernel output to VT0 - //Debug_SetKTerminal("/Devices/VTerm/0"); + Debug_SetKTerminal("/Devices/VTerm/0"); return 0; } diff --git a/Kernel/include/fs_devfs.h b/Kernel/include/fs_devfs.h index 4b29cf1b..add3eeb7 100644 --- a/Kernel/include/fs_devfs.h +++ b/Kernel/include/fs_devfs.h @@ -3,18 +3,30 @@ * Device Filesystem (DevFS) * - vfs/fs/devfs.c */ +/** + * \file fs_devfs.h + * \brief Acess Device Filesystem interface + */ #ifndef _FS_DEVFS_H #define _FS_DEVFS_H #include // === TYPES === +/** + * \brief DevFS Driver + */ typedef struct sDevFS_Driver { - struct sDevFS_Driver *Next; - char *Name; - tVFS_Node RootNode; + struct sDevFS_Driver *Next; //!< Set to NULL by drivers (used internally) + char *Name; //!< Name of the driver file/folder + tVFS_Node RootNode; //!< Root node of driver } tDevFS_Driver; // === FUNCTIONS === +/** + * \fn int DevFS_AddDevice(tDevFS_Driver *Dev) + * \brief Registers a device in the Device filesystem + * \param Dev Pointer to a persistant structure that represents the driver + */ extern int DevFS_AddDevice(tDevFS_Driver *Dev); #endif diff --git a/Kernel/include/iocache.h b/Kernel/include/iocache.h new file mode 100644 index 00000000..f008a2d0 --- /dev/null +++ b/Kernel/include/iocache.h @@ -0,0 +1,120 @@ +/* + * Acess2 Kernel + * - IO Cache + * + * By thePowersGang (John Hodge) + */ +/** + * \file iocache.h + * \brief I/O Caching Helper Subsystem + * + * The IO Cache abstracts caching of disk sectors away from the device + * driver to reduce code duplication and allow a central location for + * disk cache management that can be flushed simply by the kernel, without + * having to ask each driver to do it indivitually. + */ +#ifndef _IOCHACHE_H_ +#define _IOCHACHE_H_ + +// === TYPES === +/** + * \brief IO Cache Handle + */ +typedef struct sIOCache tIOCache; +/** + * \brief Write Callback + * + * Called to write a sector back to the device + */ +typedef int (*tIOCache_WriteCallback)(Uint32 ID, Uint64 Sector, void *Buffer); + +// === CONSTANTS === +/** + * \brief I/O Cache handling modes + */ +enum eIOCache_Modess { + /** + * \brief Writeback + * + * Transparently writes data straight to the device when the cache + * is written to. + */ + IOCACHE_WRITEBACK, + /** + * \brief Delay Write + * + * Only writes when instructed to (by ::IOCache_Flush) or when a + * cached sector is being reallocated. + */ + IOCACHE_DELAYWRITE, + /** + * \brief Virtual - No Writes + * + * Changes to the cache contents are only reflected in memory, + * any calls to ::IOCache_Flush will silently return without doing + * anything and if a sector is reallocated, all changes will be lost + */ + IOCACHE_VIRTUAL +}; + +// === FUNCTIONS === +/** + * \brief Creates a new IO Cache + * \param Write Function to call to write a sector to the device + * \param ID ID to pass to \a Write + * \param SectorSize Size of a cached sector + * \param CacheSize Maximum number of objects that can be in the cache at one time + */ +tIOCache *IOCache_Create( tIOCache_WriteCallback Write, Uint32 ID, int SectorSize, int CacheSize ); + +/** + * \brief Reads from a cached sector + * \param Cache Cache handle returned by ::IOCache_Create + * \param Sector Sector's ID number + * \param Buffer Destination for the data read + * \return 1 if the data was read, 0 if the sector is not cached, -1 on error + */ + int IOCache_Read( tIOCache *Cache, Uint64 Sector, void *Buffer ); + +/** + * \brief Adds a sector to the cache + * \param Cache Cache handle returned by ::IOCache_Create + * \param Sector Sector's ID number + * \param Buffer Data to cache + * \return 1 on success, 0 if the sector is already cached, -1 on error + */ + int IOCache_Add( tIOCache *Cache, Uint64 Sector, void *Buffer ); + +/** + * \brief Writes to a cached sector + * \param Cache Cache handle returned by ::IOCache_Create + * \param Sector Sector's ID number + * \param Buffer Data to write to the cache + * \return 1 if the data was read, 0 if the sector is not cached, -1 on error + * + * If the sector is in the cache, it is updated. + * Wether the Write callback is called depends on the selected caching + * behaviour. + */ + int IOCache_Write( tIOCache *Cache, Uint64 Sector, void *Buffer ); + +/** + * \brief Flush altered sectors out to the device + * \param Cache Cache handle returned by ::IOCache_Create + * + * This will call the cache's write callback on each altered sector + * to flush the write cache. + */ +void IOCache_Flush( tIOCache *Cache ); + +/** + * \brief Flushes the cache and then removes it + * \param Cache Cache handle returned by ::IOCache_Create + * \note After this is called \a Cache is no longer valid + * + * IOCache_Destroy writes all changed sectors to the device and then + * deallocates the cache for other systems to use. + */ +void IOCache_Destroy( tIOCache *Cache ); + +#endif diff --git a/Kernel/include/tpl_drv_common.h b/Kernel/include/tpl_drv_common.h index 31ad97a0..7608bc8a 100644 --- a/Kernel/include/tpl_drv_common.h +++ b/Kernel/include/tpl_drv_common.h @@ -1,8 +1,11 @@ +/* + * Acess2 + * - Common Driver Interface + */ /** - AcessOS Version 1 - \file tpl_drv_common.h - \brief Common Driver Interface Definitions -*/ + * \file tpl_drv_common.h + * \brief Common Driver Interface Definitions + */ #ifndef _TPL_COMMON_H #define _TPL_COMMON_H @@ -18,7 +21,7 @@ enum eTplDrv_IOCtl { /// \brief Get driver version - (int *ver) DRV_IOCTL_VERSION, /// \brief Get a IOCtl from a symbolic name - DRV_IOCTL_LOOKUP, + DRV_IOCTL_LOOKUP }; /** @@ -39,6 +42,17 @@ enum eTplDrv_Type { }; // === FUNCTIONS === +/** + * \fn int GetIOCtlId(int Class, char *Name) + * \brief Transforms a symbolic name into an ID + * \param Class ::eTplDrv_Type type to use + * \param Name Symbolic name to resolve + * + * This function is designed to be used by device drivers to implement + * ::eTplDrv_IOCtl.DRV_IOCTL_LOOKUP easily given that they conform to + * the standard interfaces (::eTplDrv_Type except DRV_TYPE_MISC) and do + * not add their own call numbers. + */ extern int GetIOCtlId(int Class, char *Name); #endif diff --git a/Kernel/include/tpl_drv_keyboard.h b/Kernel/include/tpl_drv_keyboard.h index 77f8295a..1f330039 100644 --- a/Kernel/include/tpl_drv_keyboard.h +++ b/Kernel/include/tpl_drv_keyboard.h @@ -21,9 +21,15 @@ enum eTplKeyboard_IOCtl { KB_IOCTL_SETCALLBACK }; -typedef void (*tKeybardCallback)(Uint32); +/** + * \brief Callback type for KB_IOCTL_SETCALLBACK + */ +typedef void (*tKeybardCallback)(Uint32 Key); -enum { +/** + * \brief Symbolic key codes + */ +enum eTplKeyboard_KeyCodes { KEY_ESC = 0x1B, KEY_NP_MASK = 0x80, //End of ASCII Range diff --git a/Kernel/include/tpl_drv_video.h b/Kernel/include/tpl_drv_video.h index b84a97e2..0272078e 100644 --- a/Kernel/include/tpl_drv_video.h +++ b/Kernel/include/tpl_drv_video.h @@ -44,9 +44,8 @@ enum eTplVideo_IOCtl { }; /** - \struct sVideo_IOCtl_Mode - \brief Mode Structure used in IOCtl Calls -*/ + * \brief Mode Structure used in IOCtl Calls + */ struct sVideo_IOCtl_Mode { short id; //!< Mide ID Uint16 width; //!< Width @@ -55,45 +54,76 @@ struct sVideo_IOCtl_Mode { Uint8 flags; //!< Mode Flags }; typedef struct sVideo_IOCtl_Mode tVideo_IOCtl_Mode; //!< Mode Type + +//! \name Video Mode flags +//! \{ /** * \brief Text Mode Flag * \note A text mode should have the ::sVideo_IOCtl_Mode.bpp set to 12 */ #define VIDEO_FLAG_TEXT 0x1 -#define VIDEO_FLAG_SLOW 0x2 //!< Non-accelerated mode +/** + * \brief Slow (non-accellerated mode) + */ +#define VIDEO_FLAG_SLOW 0x2 +//! \} -typedef struct sVideo_IOCtl_Pos tVideo_IOCtl_Pos; //!< Position Type /** + * \brief Describes a position in the video framebuffer */ +typedef struct sVideo_IOCtl_Pos tVideo_IOCtl_Pos; struct sVideo_IOCtl_Pos { Sint16 x; //!< X Coordinate Sint16 y; //!< Y Coordinate }; /** - * \struct sVT_Char * \brief Virtual Terminal Representation of a character */ +typedef struct sVT_Char tVT_Char; struct sVT_Char { - Uint32 Ch; + Uint32 Ch; //!< UTF-32 Character union { struct { - Uint16 BGCol; - Uint16 FGCol; + Uint16 BGCol; //!< 12-bit Foreground Colour + Uint16 FGCol; //!< 12-bit Background Colour }; - Uint32 Colour; + Uint32 Colour; //!< Compound colour for ease of access }; }; -typedef struct sVT_Char tVT_Char; +/** + * \name Basic builtin colour definitions + * \{ + */ #define VT_COL_BLACK 0x0000 #define VT_COL_GREY 0x0888 #define VT_COL_LTGREY 0x0CCC #define VT_COL_WHITE 0x0FFF +/** + * \} + */ +//! \brief Defines the width of a rendered character extern int giVT_CharWidth; +//! \brief Defines the height of a rendered character extern int giVT_CharHeight; +/** + * \fn void VT_Font_Render(Uint32 Codepoint, void *Buffer, int Pitch, Uint32 BGC, Uint32 FGC) + * \brief Renders a character to a buffer + * \param Codepoint Unicode character to render + * \param Buffer Buffer to render to (32-bpp) + * \param Pitch Number of DWords per line + * \param BGC 32-bit Background Colour + * \param FGC 32-bit Foreground Colour + */ extern void VT_Font_Render(Uint32 Codepoint, void *Buffer, int Pitch, Uint32 BGC, Uint32 FGC); +/** + * \fn Uint32 VT_Colour12to24(Uint16 Col12) + * \brief Converts a colour from 12bpp to 32bpp + * \param Col12 12-bpp input colour + * \return Expanded 32-bpp (24-bit colour) version of \a Col12 + */ extern Uint32 VT_Colour12to24(Uint16 Col12); #endif diff --git a/Kernel/include/vfs.h b/Kernel/include/vfs.h index 025a5262..6fc2491d 100644 --- a/Kernel/include/vfs.h +++ b/Kernel/include/vfs.h @@ -1,36 +1,75 @@ /* - * Acess Micro - VFS Server Ver 1 + * Acess2 + * VFS Common Header + */ +/** + * \file vfs.h + * \brief Acess VFS Layer */ #ifndef _VFS_H #define _VFS_H #include +//! \name ACL Permissions +//! \{ +/** + * \brief Readable + */ #define VFS_PERM_READ 0x00000001 +/** + * \brief Writeable + */ #define VFS_PERM_WRITE 0x00000002 +/** + * \brief Append allowed + */ #define VFS_PERM_APPEND 0x00000004 +/** + * \brief Executable + */ #define VFS_PERM_EXECUTE 0x00000008 +/** + * \brief All permissions granted + */ #define VFS_PERM_ALL 0x7FFFFFFF // Mask for permissions +/** + * \brief Denies instead of granting permissions + * \note Denials take precedence + */ #define VFS_PERM_DENY 0x80000000 // Inverts permissions +//! \} -typedef struct sVFS_ACL { +/** + * \brief ACL Defintion Structure + */ +typedef struct sVFS_ACL +{ struct { - unsigned Group: 1; // Group (as opposed to user) flag - unsigned ID: 31; // ID of Group/User (-1 for nobody/world) + unsigned Group: 1; //!< Group (as opposed to user) flag + unsigned ID: 31; //!< ID of Group/User (-1 for nobody/world) }; struct { - unsigned Inv: 1; // Invert Permissions - unsigned Perms: 31; // Permission Flags + unsigned Inv: 1; //!< Invert Permissions + unsigned Perms: 31; //!< Permission Flags }; } tVFS_ACL; -#define VFS_FFLAG_READONLY 0x01 -#define VFS_FFLAG_DIRECTORY 0x02 -#define VFS_FFLAG_SYMLINK 0x04 +/** + * \name VFS Node Flags + * \{ + */ +#define VFS_FFLAG_READONLY 0x01 //!< Read-only file +#define VFS_FFLAG_DIRECTORY 0x02 //!< Directory +#define VFS_FFLAG_SYMLINK 0x04 //!< Symbolic Link +/** + * \} + */ -typedef struct sVFS_Node { - //char *Name; //!< Node's Name (UTF-8) - +/** + * \brief VFS Node + */ +typedef struct sVFS_Node { Uint64 Inode; //!< Inode ID Uint ImplInt; //!< Implementation Usable Integer void *ImplPtr; //!< Implementation Usable Pointer @@ -58,16 +97,23 @@ typedef struct sVFS_Node { //! Send an IO Control int (*IOCtl)(struct sVFS_Node *Node, int Id, void *Data); + //! \brief Read from the file Uint64 (*Read)(struct sVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer); + //! \brief Write to the file Uint64 (*Write)(struct sVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer); - //! Find an directory entry by name + //! \brief Find an directory entry by name + //! \note The node returned must be accessable until ::tVFS_Node.Close is called struct sVFS_Node *(*FindDir)(struct sVFS_Node *Node, char *Name); - //! Read from a directory - MUST return a heap address + + //! \brief Read from a directory + //! \note MUST return a heap address char *(*ReadDir)(struct sVFS_Node *Node, int Pos); - //! Create a node in a directory + + //! \brief Create a node in a directory int (*MkNod)(struct sVFS_Node *Node, char *Name, Uint Flags); - //! Relink (Rename/Remove) a file/directory + + //! \brief Relink (Rename/Remove) a file/directory int (*Relink)(struct sVFS_Node *Node, char *OldName, char *NewName); //!< \todo Complete @@ -76,34 +122,104 @@ typedef struct sVFS_Node { /** * \brief VFS Driver (Filesystem) Definition */ -typedef struct sVFS_Driver { +typedef struct sVFS_Driver +{ + //! \brief Unique Identifier for this filesystem type char *Name; + //! \brief Flags applying to this driver Uint Flags; + + //! \brief Callback to mount a device tVFS_Node *(*InitDevice)(char *Device, char **Options); + //! \brief Callback to unmount a device void (*Unmount)(tVFS_Node *Node); + //! \brief Used internally (next driver in the chain) struct sVFS_Driver *Next; } tVFS_Driver; // === GLOBALS === +//! \brief Maximum number of elements that can be skipped in one return #define VFS_MAXSKIP ((void*)1024) +//! \brief Skip a single entry in readdir #define VFS_SKIP ((void*)1) +//! \brief Skip \a n entries in readdir #define VFS_SKIPN(n) ((void*)(n)) -extern tVFS_Node NULLNode; -extern tVFS_ACL gVFS_ACL_EveryoneRWX; -extern tVFS_ACL gVFS_ACL_EveryoneRW; -extern tVFS_ACL gVFS_ACL_EveryoneRX; -extern tVFS_ACL gVFS_ACL_EveryoneRO; + +extern tVFS_Node NULLNode; //!< NULL VFS Node (Ignored/Skipped) +/** + * \name Simple ACLs to aid writing drivers + * \{ + */ +extern tVFS_ACL gVFS_ACL_EveryoneRWX; //!< Everyone Read/Write/Execute +extern tVFS_ACL gVFS_ACL_EveryoneRW; //!< Everyone Read/Write +extern tVFS_ACL gVFS_ACL_EveryoneRX; //!< Everyone Read/Execute +extern tVFS_ACL gVFS_ACL_EveryoneRO; //!< Everyone Read only +/** + * \} + */ // === FUNCTIONS === +/** + * \fn int VFS_AddDriver(tVFS_Driver *Info) + * \brief Registers the driver with the DevFS layer + * \param Info Driver information structure + */ extern int VFS_AddDriver(tVFS_Driver *Info); +/** + * \fn tVFS_Driver *VFS_GetFSByName(char *Name) + * \brief Get the information structure of a driver given its name + * \param Name Name of filesystem driver to find + */ extern tVFS_Driver *VFS_GetFSByName(char *Name); +/** + * \fn tVFS_ACL *VFS_UnixToAcessACL(Uint Mode, Uint Owner, Uint Group) + * \brief Transforms Unix Permssions into Acess ACLs + * \param Mode Unix RWXrwxRWX mask + * \param Owner UID of the file's owner + * \param Group GID of the file's owning group + * \return An array of 3 Acess ACLs + */ extern tVFS_ACL *VFS_UnixToAcessACL(Uint Mode, Uint Owner, Uint Group); // --- Node Cache -- +//! \name Node Cache +//! \{ +/** + * \fn int Inode_GetHandle() + * \brief Gets a unique handle to the Node Cache + * \return A unique handle for use for the rest of the Inode_* functions + */ extern int Inode_GetHandle(); +/** + * \fn tVFS_Node *Inode_GetCache(int Handle, Uint64 Inode) + * \brief Gets an inode from the node cache + * \param Handle A handle returned by Inode_GetHandle() + * \param Inode Value of the Inode field of the ::tVFS_Node you want + * \return A pointer to the cached node + */ extern tVFS_Node *Inode_GetCache(int Handle, Uint64 Inode); +/** + * \fn tVFS_Node *Inode_CacheNode(int Handle, tVFS_Node *Node) + * \brief Caches a node in the Node Cache + * \param Handle A handle returned by Inode_GetHandle() + * \param Node A pointer to the node to be cached (a copy is taken) + * \return A pointer to the node in the node cache + */ extern tVFS_Node *Inode_CacheNode(int Handle, tVFS_Node *Node); +/** + * \fn void Inode_UncacheNode(int Handle, Uint64 Inode) + * \brief Dereferences (and removes if needed) a node from the cache + * \param Handle A handle returned by Inode_GetHandle() + * \param Inode Value of the Inode field of the ::tVFS_Node you want to remove + */ extern void Inode_UncacheNode(int Handle, Uint64 Inode); +/** + * \fn void Inode_ClearCache(int Handle) + * \brief Clears the cache for a handle + * \param Handle A handle returned by Inode_GetHandle() + */ extern void Inode_ClearCache(int Handle); +//! \} + #endif diff --git a/Makefile.cfg b/Makefile.cfg index 17524975..a8d3b200 100644 --- a/Makefile.cfg +++ b/Makefile.cfg @@ -15,8 +15,8 @@ ARCH = i386 ARCHDIR = x86 FILESYSTEMS = fat ext2 -DRIVERS = ata_x86 fdd -MODULES = NE2000 BochsVBE +DRIVERS = ata_x86 +MODULES = FDD NE2000 BochsVBE DISTROOT = /mnt/AcessHDD/Acess2 ACESSDIR = /home/hodgeja/Projects/Acess2 diff --git a/Modules/FDD/Makefile b/Modules/FDD/Makefile new file mode 100644 index 00000000..15965531 --- /dev/null +++ b/Modules/FDD/Makefile @@ -0,0 +1,7 @@ +# +# + +OBJ = fdd.o +NAME = FDD + +-include ../Makefile.tpl diff --git a/Kernel/drv/fdd.c b/Modules/FDD/fdd.c similarity index 86% rename from Kernel/drv/fdd.c rename to Modules/FDD/fdd.c index 3c86b08b..c33b2818 100644 --- a/Kernel/drv/fdd.c +++ b/Modules/FDD/fdd.c @@ -2,12 +2,13 @@ * AcessOS 0.1 * Floppy Disk Access Code */ -#define DEBUG 1 +#define DEBUG 0 #include #include #include #include #include +#include #define WARN 0 @@ -83,7 +84,8 @@ tVFS_Node *FDD_FindDir(tVFS_Node *dirNode, char *Name); int FDD_IOCtl(tVFS_Node *Node, int ID, void *Data); Uint64 FDD_ReadFS(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer); // --- Raw Disk Access - int FDD_ReadSector(int disk, int lba, void *buf); + int FDD_ReadSector(Uint32 disk, Uint64 lba, void *Buffer); + int FDD_WriteSector(Uint32 Disk, Uint64 LBA, void *Buffer); // --- Helpers void FDD_IRQHandler(int Num); void FDD_WaitIRQ(); @@ -175,6 +177,19 @@ int FDD_Install(char **Arguments) #if USE_CACHE //sFDD_SectorCache = malloc(sizeof(*sFDD_SectorCache)*CACHE_SIZE); //siFDD_SectorCacheSize = CACHE_SIZE; + #else + if( cFDD_SIZES[data >> 4] ) { + gFDD_Devices[0].CacheHandle = IOCache_Create( + FDD_WriteSector, 0, 512, + gFDD_Devices[0].Node.Size / (512*4) + ); // Cache is 1/4 the size of the disk + } + if( cFDD_SIZES[data & 15] ) { + gFDD_Devices[1].CacheHandle = IOCache_Create( + FDD_WriteSector, 0, 512, + gFDD_Devices[1].Node.Size / (512*4) + ); // Cache is 1/4 the size of the disk + } #endif // Register with devfs @@ -348,26 +363,27 @@ Uint64 FDD_ReadFS(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer) } /** - * \fn int FDD_ReadSector(int disk, int lba, void *buf) + * \fn int FDD_ReadSector(Uint32 Disk, Uint64 SectorAddr, void *Buffer) * \fn Read a sector from disk */ -int FDD_ReadSector(int disk, int lba, void *buf) +int FDD_ReadSector(Uint32 Disk, Uint64 SectorAddr, void *Buffer) { int cyl, head, sec; int spt, base; int i; + int lba = SectorAddr; - ENTER("idisk xlba pbuf", disk, lba, buf); + ENTER("idisk Xlba pbuf", disk, lba, buf); #if USE_CACHE FDD_AquireCacheSpinlock(); - for(i=0;i>1]; + base = cPORTBASE[Disk>>1]; LOG("Calculating Disk Dimensions"); //Get CHS position - if(FDD_int_GetDims(gFDD_Devices[disk].type, lba, &cyl, &head, &sec, &spt) != 1) { + if(FDD_int_GetDims(gFDD_Devices[Disk].type, lba, &cyl, &head, &sec, &spt) != 1) { LEAVE('i', -1); return -1; } // Remove Old Timer - Time_RemoveTimer(gFDD_Devices[disk].timer); + Time_RemoveTimer(gFDD_Devices[Disk].timer); // Check if Motor is on - if(gFDD_Devices[disk].motorState == 0) { - FDD_int_StartMotor(disk); + if(gFDD_Devices[Disk].motorState == 0) { + FDD_int_StartMotor(Disk); } LOG("Wait for Motor Spinup"); // Wait for spinup - while(gFDD_Devices[disk].motorState == 1) Threads_Yield(); + while(gFDD_Devices[Disk].motorState == 1) Threads_Yield(); LOG("C:%i,H:%i,S:%i", cyl, head, sec); LOG("Acquire Spinlock"); @@ -407,7 +428,7 @@ int FDD_ReadSector(int disk, int lba, void *buf) // Seek to track outb(base+CALIBRATE_DRIVE, 0); i = 0; - while(FDD_int_SeekTrack(disk, head, (Uint8)cyl) == 0 && i++ < FDD_SEEK_TIMEOUT ) Threads_Yield(); + while(FDD_int_SeekTrack(Disk, head, (Uint8)cyl) == 0 && i++ < FDD_SEEK_TIMEOUT ) Threads_Yield(); //FDD_SensInt(base, NULL, NULL); // Wait for IRQ LOG("Setting DMA for read"); @@ -420,7 +441,7 @@ int FDD_ReadSector(int disk, int lba, void *buf) //Threads_Wait(100); // Wait for Head to settle Time_Delay(100); FDD_int_SendByte(base, READ_SECTOR); // Was 0xE6 - FDD_int_SendByte(base, (head << 2) | (disk&1)); + FDD_int_SendByte(base, (head << 2) | (Disk&1)); FDD_int_SendByte(base, (Uint8)cyl); FDD_int_SendByte(base, (Uint8)head); FDD_int_SendByte(base, (Uint8)sec); @@ -435,7 +456,7 @@ int FDD_ReadSector(int disk, int lba, void *buf) // Read Data from DMA LOG(" FDD_ReadSector: Reading Data"); - DMA_ReadData(2, 512, buf); + DMA_ReadData(2, 512, Buffer); // Clear Input Buffer LOG("Clearing Input Buffer"); @@ -447,7 +468,7 @@ int FDD_ReadSector(int disk, int lba, void *buf) FDD_FreeSpinlock(); //Set timer to turn off motor affter a gap - gFDD_Devices[disk].timer = Time_CreateTimer(MOTOR_OFF_DELAY, FDD_int_StopMotor, (void*)disk); //One Shot Timer + gFDD_Devices[Disk].timer = Time_CreateTimer(MOTOR_OFF_DELAY, FDD_int_StopMotor, (void*)Disk); //One Shot Timer #if USE_CACHE { @@ -463,11 +484,13 @@ int FDD_ReadSector(int disk, int lba, void *buf) oldest = i; } sFDD_SectorCache[oldest].timestamp = now(); - sFDD_SectorCache[oldest].disk = disk; + sFDD_SectorCache[oldest].disk = Disk; sFDD_SectorCache[oldest].sector = lba; - memcpy(sFDD_SectorCache[oldest].data, buf, 512); + memcpy(sFDD_SectorCache[oldest].data, Buffer, 512); FDD_FreeCacheSpinlock(); } + #else + IOCache_Add( gFDD_Devices[Disk].CacheHandle, SectorAddr, Buffer ); #endif LEAVE('i', 1); @@ -738,7 +761,7 @@ void FDD_int_StartMotor(int disk) state |= 1 << (4+disk); outb( cPORTBASE[ disk>>1 ] + PORT_DIGOUTPUT, state ); gFDD_Devices[disk].motorState = 1; - gFDD_Devices[disk].timer = Time_CreateTimer(MOTOR_ON_DELAY, FDD_int_TimerCallback, (void*)disk); //One Shot Timer + gFDD_Devices[disk].timer = Time_CreateTimer(MOTOR_ON_DELAY, FDD_int_TimerCallback, (void*)disk); } /** diff --git a/Modules/Makefile.tpl b/Modules/Makefile.tpl index 41743443..64cf4b55 100644 --- a/Modules/Makefile.tpl +++ b/Modules/Makefile.tpl @@ -24,7 +24,7 @@ clean: $(BIN): $(OBJ) @echo --- $(LD) -o $@ @$(LD) -T ../link.ld -shared -o $@ $(OBJ) - @echo --- $(LD) -o ../$(NAME).o.$(ARCH) + @echo --- $(LD) -o $(KOBJ) @$(CC) -Wl,-r -nostdlib -o $(KOBJ) $(OBJ) %.o.$(ARCH): %.c Makefile ../Makefile.tpl ../../Makefile.cfg -- 2.20.1