# Project related configuration options
#---------------------------------------------------------------------------
+LAYOUT_FILE = DoxygenLayout.xml
+
# This tag specifies the encoding used for all characters in the config file
# that follow. The default is UTF-8 which is also the encoding used for all
# text before the first occurrence of this tag. Doxygen uses libiconv (or the
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
-INPUT = include/vfs.h include/fs_devfs.h include/iocache.h include/
+INPUT = include/apidoc_mainpage.h \
+ include/binary.h \
+ include/vfs.h include/vfs_ext.h \
+ include/fs_devfs.h \
+ include/iocache.h include/
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
-BUILD_NUM = 1041
+BUILD_NUM = 1068
#endif
typedef Uint32 tVAddr;
-typedef void (*tThreadFunction)(void*);
-
typedef struct {
Uint gs, fs, es, ds;
Uint edi, esi, ebp, kesp;
Uint EIP, ESP, EBP;
} tTaskState;
-// --- Interface Flags & Macros
-#define CLONE_VM 0x10
-
#endif // !defined(_ARCH_H_)
if( gaPageDir[Addr>>22] & PF_PRESENT )
Log("gaPageTable[0x%x] = 0x%x", Addr>>12, gaPageTable[Addr>>12]);
- MM_DumpTables(0, -1);
+ //MM_DumpTables(0, -1);
- Panic("Page Fault at 0x%x\n", Regs->eip);
+ Panic("Page Fault at 0x%x (Accessed 0x%x)", Regs->eip, Addr);
}
/**
/**
- * \fn int MM_IsUser(tVAddr Addr)
+ * \fn int MM_IsUser(tVAddr VAddr)
* \brief Checks if a page is user accessable
*/
-int MM_IsUser(tVAddr Addr)
+int MM_IsUser(tVAddr VAddr)
{
- if( !(gaPageDir[Addr >> 22] & 1) )
+ if( !(gaPageDir[VAddr >> 22] & 1) )
return 0;
- if( !(gaPageTable[Addr >> 12] & 1) )
+ if( !(gaPageTable[VAddr >> 12] & 1) )
return 0;
- if( !(gaPageTable[Addr >> 12] & PF_USER) )
+ if( !(gaPageTable[VAddr >> 12] & PF_USER) )
return 0;
return 1;
}
--- /dev/null
+Acess2 Binary File Loader Specifcation
+--------------------------------------
+
+Binary file loaders are defined by creating a \a tBinaryType variable that
+is registered with the kernel.
+
+\a tBinaryType contains seven fields.
+-# \a Next
+ This field is used internally by the kernel and should be set to NULL
+ when the definition is initialise and not changed by the driver.
+-# \a Ident
+ This field tells the kernel how to recognise this file format. If the
+ first 32-bits of the file (ANDed with the \a Mask field) match this
+ value, the file will be passed to this loader.
+-# \a Mask
+ Determines what bits in the first 32-bits of the file matter for the
+ identifcation.
+-# \a Name
+ This is a C string that uniquely identifies this binary format.
+-# \a Load
+ This field is a pointer to a function that takes a VFS Handle of the
+ source exectuable file as an argument and returns a \a tBinary
+ pointer that defines the location and attributes of the exectable's
+ segments. (See \a tBinary for more information)
+++ /dev/null
-/**\r
- Acess v1\r
- \file bin_elf.h\r
- \brief ELF Exeutable Loader\r
-*/\r
-#ifndef _BIN_ELF_H\r
-#define _BIN_ELF_H\r
-\r
-/**\r
- \struct elf_header_s\r
- \brief ELF File Header\r
-*/\r
-struct sElf32_Ehdr {\r
- union {\r
- char ident[16]; //!< Identifier Bytes\r
- struct {\r
- Uint Ident1;\r
- Uint Ident2;\r
- Uint HashTable;\r
- Uint SymTable;\r
- } misc;\r
- };\r
- Uint16 filetype; //!< File Type\r
- Uint16 machine; //!< Machine / Arch\r
- Uint32 version; //!< Version (File?)\r
- Uint32 entrypoint; //!< Entry Point\r
- Uint32 phoff; //!< Program Header Offset\r
- Uint32 shoff; //!< Section Header Offset\r
- Uint32 flags; //!< Flags\r
- Uint16 headersize; //!< Header Size\r
- Uint16 phentsize; //!< Program Header Entry Size\r
- Uint16 phentcount; //!< Program Header Entry Count\r
- Uint16 shentsize; //!< Section Header Entry Size\r
- Uint16 shentcount; //!< Section Header Entry Count\r
- Uint16 shstrindex; //!< Section Header String Table Index\r
-};\r
-\r
-/**\r
- \name Executable Types\r
- \{\r
-*/\r
-#define ET_NONE 0 //!< NULL Type\r
-#define ET_REL 1 //!< Relocatable (Object)\r
-#define ET_EXEC 2 //!< Executable\r
-#define ET_DYN 3 //!< Dynamic Library\r
-#define ET_CORE 4 //!< Core?\r
-#define ET_LOPROC 0xFF00 //!< Low Impl Defined\r
-#define ET_HIPROC 0xFFFF //!< High Impl Defined\r
-//! \}\r
-\r
-/**\r
- \name Section IDs\r
- \{\r
-*/\r
-#define SHN_UNDEF 0 //!< Undefined Section\r
-#define SHN_LORESERVE 0xFF00 //!< Low Reserved\r
-#define SHN_LOPROC 0xFF00 //!< Low Impl Defined\r
-#define SHN_HIPROC 0xFF1F //!< High Impl Defined\r
-#define SHN_ABS 0xFFF1 //!< Absolute Address (Base: 0, Size: -1)\r
-#define SHN_COMMON 0xFFF2 //!< Common\r
-#define SHN_HIRESERVE 0xFFFF //!< High Reserved\r
-//! \}\r
-\r
-/**\r
- \enum eElfSectionTypes\r
- \brief ELF Section Types\r
-*/\r
-enum eElfSectionTypes {\r
- SHT_NULL, //0\r
- SHT_PROGBITS, //1\r
- SHT_SYMTAB, //2\r
- SHT_STRTAB, //3\r
- SHT_RELA, //4\r
- SHT_HASH, //5\r
- SHT_DYNAMIC, //6\r
- SHT_NOTE, //7\r
- SHT_NOBITS, //8\r
- SHT_REL, //9\r
- SHT_SHLIB, //A\r
- SHT_DYNSYM, //B\r
- SHT_LAST, //C\r
- SHT_LOPROC = 0x70000000,\r
- SHT_HIPROC = 0x7fffffff,\r
- SHT_LOUSER = 0x80000000,\r
- SHT_HIUSER = 0xffffffff\r
-};\r
-\r
-#define SHF_WRITE 0x1\r
-#define SHF_ALLOC 0x2\r
-#define SHF_EXECINSTR 0x4\r
-#define SHF_MASKPROC 0xf0000000\r
-\r
-struct sElf32_Shent {\r
- Uint32 name;\r
- Uint32 type;\r
- Uint32 flags;\r
- Uint32 address;\r
- Uint32 offset;\r
- Uint32 size;\r
- Uint32 link;\r
- Uint32 info;\r
- Uint32 addralign;\r
- Uint32 entsize;\r
-}; //sizeof = 40\r
-\r
-struct elf_sym_s {\r
- union {\r
- Uint32 nameOfs;\r
- char *name;\r
- };\r
- Uint32 value; //Address\r
- Uint32 size;\r
- Uint8 info;\r
- Uint8 other;\r
- Uint16 shndx;\r
-};\r
-#define STN_UNDEF 0 // Undefined Symbol\r
-\r
-enum {\r
- PT_NULL, //0\r
- PT_LOAD, //1\r
- PT_DYNAMIC, //2\r
- PT_INTERP, //3\r
- PT_NOTE, //4\r
- PT_SHLIB, //5\r
- PT_PHDR, //6\r
- PT_LOPROC = 0x70000000,\r
- PT_HIPROC = 0x7fffffff\r
-};\r
-\r
-struct sElf32_Phdr {\r
- Uint32 Type;\r
- Uint Offset;\r
- Uint VAddr;\r
- Uint PAddr;\r
- Uint32 FileSize;\r
- Uint32 MemSize;\r
- Uint32 Flags;\r
- Uint32 Align;\r
-};\r
-\r
-struct elf32_rel_s {\r
- Uint32 r_offset;\r
- Uint32 r_info;\r
-};\r
-\r
-struct elf32_rela_s {\r
- Uint32 r_offset;\r
- Uint32 r_info;\r
- Sint32 r_addend;\r
-};\r
-\r
-enum {\r
- R_386_NONE=0, // none\r
- R_386_32, // S+A\r
- R_386_PC32, // S+A-P\r
- R_386_GOT32, // G+A-P\r
- R_386_PLT32, // L+A-P\r
- R_386_COPY, // none\r
- R_386_GLOB_DAT, // S\r
- R_386_JMP_SLOT, // S\r
- R_386_RELATIVE, // B+A\r
- R_386_GOTOFF, // S+A-GOT\r
- R_386_GOTPC, // GOT+A-P\r
- R_386_LAST // none\r
-};\r
-\r
-#define ELF32_R_SYM(i) ((i)>>8) // Takes an info value and returns a symbol index\r
-#define ELF32_R_TYPE(i) ((i)&0xFF) // Takes an info value and returns a type\r
-#define ELF32_R_INFO(s,t) (((s)<<8)+((t)&0xFF)) // Takes a type and symbol index and returns an info value\r
-\r
-struct elf32_dyn_s {\r
- Uint16 d_tag;\r
- Uint32 d_val; //Also d_ptr\r
-};\r
-\r
-enum {\r
- DT_NULL, //!< Marks End of list\r
- DT_NEEDED, //!< Offset in strtab to needed library\r
- DT_PLTRELSZ, //!< Size in bytes of PLT\r
- DT_PLTGOT, //!< Address of PLT/GOT\r
- DT_HASH, //!< Address of symbol hash table\r
- DT_STRTAB, //!< String Table address\r
- DT_SYMTAB, //!< Symbol Table address\r
- DT_RELA, //!< Relocation table address\r
- DT_RELASZ, //!< Size of relocation table\r
- DT_RELAENT, //!< Size of entry in relocation table\r
- DT_STRSZ, //!< Size of string table\r
- DT_SYMENT, //!< Size of symbol table entry\r
- DT_INIT, //!< Address of initialisation function\r
- DT_FINI, //!< Address of termination function\r
- DT_SONAME, //!< String table offset of so name\r
- DT_RPATH, //!< String table offset of library path\r
- DT_SYMBOLIC,//!< Reverse order of symbol searching for library, search libs first then executable\r
- DT_REL, //!< Relocation Entries (Elf32_Rel instead of Elf32_Rela)\r
- DT_RELSZ, //!< Size of above table (bytes)\r
- DT_RELENT, //!< Size of entry in above table\r
- DT_PLTREL, //!< Relocation entry of PLT\r
- DT_DEBUG, //!< Debugging Entry - Unknown contents\r
- DT_TEXTREL, //!< Indicates that modifcations to a non-writeable segment may occur\r
- DT_JMPREL, //!< Address of PLT only relocation entries\r
- DT_LOPROC = 0x70000000, //!< Low Definable\r
- DT_HIPROC = 0x7FFFFFFF //!< High Definable\r
-};\r
-\r
-typedef struct sElf32_Ehdr Elf32_Ehdr;\r
-typedef struct sElf32_Phdr Elf32_Phdr;\r
-typedef struct sElf32_Shent Elf32_Shent;\r
-typedef struct elf_sym_s elf_symtab;\r
-typedef struct elf_sym_s Elf32_Sym;\r
-typedef struct elf32_rel_s Elf32_Rel;\r
-typedef struct elf32_rela_s Elf32_Rela;\r
-typedef struct elf32_dyn_s Elf32_Dyn;\r
-\r
-#endif // defined(_EXE_ELF_H)\r
/*\r
-Acess v0.1\r
-ELF Executable Loader Code\r
-*/\r
+ * Acess v0.1\r
+ * ELF Executable Loader Code\r
+ */\r
+#define DEBUG 0\r
#include <common.h>\r
#include <binary.h>\r
-#include "bin_elf.h"\r
+#include "elf.h"\r
\r
-#define DEBUG 0\r
#define DEBUG_WARN 1\r
\r
-#if DEBUG\r
-# define DEBUGS(v...) Log(v)\r
-#else\r
-# define DEBUGS(v...)\r
-# undef ENTER\r
-# undef LOG\r
-# undef LEAVE\r
-# define ENTER(...)\r
-# define LOG(...)\r
-# define LEAVE(...)\r
-#endif\r
-\r
\r
// === PROTOTYPES ===\r
tBinary *Elf_Load(int fp);\r
--- /dev/null
+/**\r
+ Acess v1\r
+ \file bin_elf.h\r
+ \brief ELF Exeutable Loader\r
+*/\r
+#ifndef _BIN_ELF_H\r
+#define _BIN_ELF_H\r
+\r
+/**\r
+ \struct elf_header_s\r
+ \brief ELF File Header\r
+*/\r
+struct sElf32_Ehdr {\r
+ union {\r
+ char ident[16]; //!< Identifier Bytes\r
+ struct {\r
+ Uint Ident1;\r
+ Uint Ident2;\r
+ Uint HashTable;\r
+ Uint SymTable;\r
+ } misc;\r
+ };\r
+ Uint16 filetype; //!< File Type\r
+ Uint16 machine; //!< Machine / Arch\r
+ Uint32 version; //!< Version (File?)\r
+ Uint32 entrypoint; //!< Entry Point\r
+ Uint32 phoff; //!< Program Header Offset\r
+ Uint32 shoff; //!< Section Header Offset\r
+ Uint32 flags; //!< Flags\r
+ Uint16 headersize; //!< Header Size\r
+ Uint16 phentsize; //!< Program Header Entry Size\r
+ Uint16 phentcount; //!< Program Header Entry Count\r
+ Uint16 shentsize; //!< Section Header Entry Size\r
+ Uint16 shentcount; //!< Section Header Entry Count\r
+ Uint16 shstrindex; //!< Section Header String Table Index\r
+};\r
+\r
+/**\r
+ \name Executable Types\r
+ \{\r
+*/\r
+#define ET_NONE 0 //!< NULL Type\r
+#define ET_REL 1 //!< Relocatable (Object)\r
+#define ET_EXEC 2 //!< Executable\r
+#define ET_DYN 3 //!< Dynamic Library\r
+#define ET_CORE 4 //!< Core?\r
+#define ET_LOPROC 0xFF00 //!< Low Impl Defined\r
+#define ET_HIPROC 0xFFFF //!< High Impl Defined\r
+//! \}\r
+\r
+/**\r
+ \name Section IDs\r
+ \{\r
+*/\r
+#define SHN_UNDEF 0 //!< Undefined Section\r
+#define SHN_LORESERVE 0xFF00 //!< Low Reserved\r
+#define SHN_LOPROC 0xFF00 //!< Low Impl Defined\r
+#define SHN_HIPROC 0xFF1F //!< High Impl Defined\r
+#define SHN_ABS 0xFFF1 //!< Absolute Address (Base: 0, Size: -1)\r
+#define SHN_COMMON 0xFFF2 //!< Common\r
+#define SHN_HIRESERVE 0xFFFF //!< High Reserved\r
+//! \}\r
+\r
+/**\r
+ \enum eElfSectionTypes\r
+ \brief ELF Section Types\r
+*/\r
+enum eElfSectionTypes {\r
+ SHT_NULL, //0\r
+ SHT_PROGBITS, //1\r
+ SHT_SYMTAB, //2\r
+ SHT_STRTAB, //3\r
+ SHT_RELA, //4\r
+ SHT_HASH, //5\r
+ SHT_DYNAMIC, //6\r
+ SHT_NOTE, //7\r
+ SHT_NOBITS, //8\r
+ SHT_REL, //9\r
+ SHT_SHLIB, //A\r
+ SHT_DYNSYM, //B\r
+ SHT_LAST, //C\r
+ SHT_LOPROC = 0x70000000,\r
+ SHT_HIPROC = 0x7fffffff,\r
+ SHT_LOUSER = 0x80000000,\r
+ SHT_HIUSER = 0xffffffff\r
+};\r
+\r
+#define SHF_WRITE 0x1\r
+#define SHF_ALLOC 0x2\r
+#define SHF_EXECINSTR 0x4\r
+#define SHF_MASKPROC 0xf0000000\r
+\r
+struct sElf32_Shent {\r
+ Uint32 name;\r
+ Uint32 type;\r
+ Uint32 flags;\r
+ Uint32 address;\r
+ Uint32 offset;\r
+ Uint32 size;\r
+ Uint32 link;\r
+ Uint32 info;\r
+ Uint32 addralign;\r
+ Uint32 entsize;\r
+}; //sizeof = 40\r
+\r
+struct elf_sym_s {\r
+ union {\r
+ Uint32 nameOfs;\r
+ char *name;\r
+ };\r
+ Uint32 value; //Address\r
+ Uint32 size;\r
+ Uint8 info;\r
+ Uint8 other;\r
+ Uint16 shndx;\r
+};\r
+#define STN_UNDEF 0 // Undefined Symbol\r
+\r
+enum {\r
+ PT_NULL, //0\r
+ PT_LOAD, //1\r
+ PT_DYNAMIC, //2\r
+ PT_INTERP, //3\r
+ PT_NOTE, //4\r
+ PT_SHLIB, //5\r
+ PT_PHDR, //6\r
+ PT_LOPROC = 0x70000000,\r
+ PT_HIPROC = 0x7fffffff\r
+};\r
+\r
+struct sElf32_Phdr {\r
+ Uint32 Type;\r
+ Uint Offset;\r
+ Uint VAddr;\r
+ Uint PAddr;\r
+ Uint32 FileSize;\r
+ Uint32 MemSize;\r
+ Uint32 Flags;\r
+ Uint32 Align;\r
+};\r
+\r
+struct elf32_rel_s {\r
+ Uint32 r_offset;\r
+ Uint32 r_info;\r
+};\r
+\r
+struct elf32_rela_s {\r
+ Uint32 r_offset;\r
+ Uint32 r_info;\r
+ Sint32 r_addend;\r
+};\r
+\r
+enum {\r
+ R_386_NONE = 0, // none\r
+ R_386_32, // S+A\r
+ R_386_PC32, // S+A-P\r
+ R_386_GOT32, // G+A-P\r
+ R_386_PLT32, // L+A-P\r
+ R_386_COPY, // none\r
+ R_386_GLOB_DAT, // S\r
+ R_386_JMP_SLOT, // S\r
+ R_386_RELATIVE, // B+A\r
+ R_386_GOTOFF, // S+A-GOT\r
+ R_386_GOTPC, // GOT+A-P\r
+ R_386_LAST // none\r
+};\r
+\r
+#define ELF32_R_SYM(i) ((i)>>8) // Takes an info value and returns a symbol index\r
+#define ELF32_R_TYPE(i) ((i)&0xFF) // Takes an info value and returns a type\r
+#define ELF32_R_INFO(s,t) (((s)<<8)+((t)&0xFF)) // Takes a type and symbol index and returns an info value\r
+\r
+struct elf32_dyn_s {\r
+ Uint32 d_tag;\r
+ Uint32 d_val; //Also d_ptr\r
+};\r
+\r
+enum {\r
+ DT_NULL, //!< Marks End of list\r
+ DT_NEEDED, //!< Offset in strtab to needed library\r
+ DT_PLTRELSZ, //!< Size in bytes of PLT\r
+ DT_PLTGOT, //!< Address of PLT/GOT\r
+ DT_HASH, //!< Address of symbol hash table\r
+ DT_STRTAB, //!< String Table address\r
+ DT_SYMTAB, //!< Symbol Table address\r
+ DT_RELA, //!< Relocation table address\r
+ DT_RELASZ, //!< Size of relocation table\r
+ DT_RELAENT, //!< Size of entry in relocation table\r
+ DT_STRSZ, //!< Size of string table\r
+ DT_SYMENT, //!< Size of symbol table entry\r
+ DT_INIT, //!< Address of initialisation function\r
+ DT_FINI, //!< Address of termination function\r
+ DT_SONAME, //!< String table offset of so name\r
+ DT_RPATH, //!< String table offset of library path\r
+ DT_SYMBOLIC,//!< Reverse order of symbol searching for library, search libs first then executable\r
+ DT_REL, //!< Relocation Entries (Elf32_Rel instead of Elf32_Rela)\r
+ DT_RELSZ, //!< Size of above table (bytes)\r
+ DT_RELENT, //!< Size of entry in above table\r
+ DT_PLTREL, //!< Relocation entry of PLT\r
+ DT_DEBUG, //!< Debugging Entry - Unknown contents\r
+ DT_TEXTREL, //!< Indicates that modifcations to a non-writeable segment may occur\r
+ DT_JMPREL, //!< Address of PLT only relocation entries\r
+ DT_LOPROC = 0x70000000, //!< Low Definable\r
+ DT_HIPROC = 0x7FFFFFFF //!< High Definable\r
+};\r
+\r
+typedef struct sElf32_Ehdr Elf32_Ehdr;\r
+typedef struct sElf32_Phdr Elf32_Phdr;\r
+typedef struct sElf32_Shent Elf32_Shent;\r
+typedef struct elf_sym_s elf_symtab;\r
+typedef struct elf_sym_s Elf32_Sym;\r
+typedef struct elf32_rel_s Elf32_Rel;\r
+typedef struct elf32_rela_s Elf32_Rela;\r
+typedef struct elf32_dyn_s Elf32_Dyn;\r
+\r
+#endif // defined(_EXE_ELF_H)\r
#include <common.h>
#include <stdarg.h>
+#define DEBUG_TO_E9 1
+#define DEBUG_TO_SERIAL 1
+#define SERIAL_PORT 0x3F8
+
// === IMPORTS ===
extern void Threads_Dump();
// === GLOBALS ===
int gDebug_Level = 0;
int giDebug_KTerm = -1;
+ int gbDebug_SerialSetup = 0;
// === CODE ===
static void E9(char ch)
{
if(giDebug_KTerm != -1)
VFS_Write(giDebug_KTerm, 1, &ch);
+
+ #if DEBUG_TO_SERIAL
+ if(!gbDebug_SerialSetup) {
+ outb(SERIAL_PORT + 1, 0x00); // Disable all interrupts
+ outb(SERIAL_PORT + 3, 0x80); // Enable DLAB (set baud rate divisor)
+ outb(SERIAL_PORT + 0, 0x03); // Set divisor to 3 (lo byte) 38400 baud
+ outb(SERIAL_PORT + 1, 0x00); // (hi byte)
+ outb(SERIAL_PORT + 3, 0x03); // 8 bits, no parity, one stop bit
+ outb(SERIAL_PORT + 2, 0xC7); // Enable FIFO with 14-byte threshold and clear it
+ outb(SERIAL_PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set
+ gbDebug_SerialSetup = 1;
+ }
+ while( (inb(SERIAL_PORT + 5) & 0x20) == 0 );
+ outb(SERIAL_PORT, ch);
+ #endif
+
+ #if DEBUG_TO_E9
__asm__ __volatile__ ( "outb %%al, $0xe9" :: "a"(((Uint8)ch)) );
+ #endif
}
static void E9_Str(char *Str)
* Acess2 IDE Harddisk Driver
* drv/ide.c
*/
-#define DEBUG 0
+#define DEBUG 1
#include <common.h>
#include <modules.h>
#include <vfs.h>
#include <fs_devfs.h>
#include <drv_pci.h>
#include <tpl_drv_common.h>
-#include <drvutil.h>
+#include <tpl_drv_disk.h>
+
+// --- Flags ---
+#define START_BEFORE_CMD 0
// === CONSTANTS ===
#define MAX_ATA_DISKS 4
int ATA_SetupIO()
{
int ent;
- Uint addr;
+ tPAddr addr;
ENTER("");
// Get IDE Controller's PCI Entry
ent = PCI_GetDeviceByClass(0x0101, 0xFFFF, -1);
- LOG("ent = %i\n", ent);
+ LOG("ent = %i", ent);
gATA_BusMasterBase = PCI_GetBAR4( ent );
- LOG("gATA_BusMasterBase = 0x%x\n", gATA_BusMasterBase);
if( gATA_BusMasterBase == 0 ) {
Warning("It seems that there is no Bus Master Controller on this machine, get one");
LEAVE('i', 0);
gATA_BusMasterBasePtr = (void*)(0xC0000000|gATA_BusMasterBase);
else
gATA_BusMasterBasePtr = (void*)( MM_MapHWPage( gATA_BusMasterBase, 1 ) + (gATA_BusMasterBase&0xFFF) );
+ LOG("gATA_BusMasterBasePtr = %p", gATA_BusMasterBasePtr);
+ }
+ else {
+ // Bit 0 is left set as a flag to other functions
+ LOG("gATA_BusMasterBase = 0x%x", gATA_BusMasterBase & ~1);
}
IRQ_AddHandler( gATA_IRQPri, ATA_IRQHandlerPri );
gATA_PRDTs[0].PBufAddr = MM_GetPhysAddr( (Uint)&gATA_Buffers[0] );
gATA_PRDTs[1].PBufAddr = MM_GetPhysAddr( (Uint)&gATA_Buffers[1] );
- LOG("gATA_PRDTs = {0x%x, 0x%x}", gATA_PRDTs[0].PBufAddr, gATA_PRDTs[1].PBufAddr);
+ LOG("gATA_PRDTs = {PBufAddr: 0x%x, PBufAddr: 0x%x}", gATA_PRDTs[0].PBufAddr, gATA_PRDTs[1].PBufAddr);
addr = MM_GetPhysAddr( (Uint)&gATA_PRDTs[0] );
+ LOG("addr = 0x%x", addr);
ATA_int_BusMasterWriteDWord(4, addr);
addr = MM_GetPhysAddr( (Uint)&gATA_PRDTs[1] );
+ LOG("addr = 0x%x", addr);
ATA_int_BusMasterWriteDWord(12, addr);
+ outb(IDE_PRI_BASE+1, 1);
+ outb(IDE_SEC_BASE+1, 1);
+
LEAVE('i', 1);
return 1;
}
int i;
tVFS_Node *node;
+ ENTER("iDisk", Disk);
+
base = ATA_GetBasePort( Disk );
+ LOG("base = 0x%x", base);
+
// Send Disk Selector
if(Disk == 1 || Disk == 3)
outb(base+6, 0xB0);
// Send IDENTIFY
outb(base+7, 0xEC);
val = inb(base+7); // Read status
- if(val == 0) return 0; // Disk does not exist
+ if(val == 0) {
+ LEAVE('i', 0);
+ return 0; // Disk does not exist
+ }
// Poll until BSY clears and DRQ sets or ERR is set
while( ((val & 0x80) || !(val & 0x08)) && !(val & 1)) val = inb(base+7);
- if(val & 1) return 0; // Error occured, so return false
+ if(val & 1) {
+ LEAVE('i', 0);
+ return 0; // Error occured, so return false
+ }
// Read Data
for(i=0;i<256;i++) buf[i] = inw(base);
gATA_Disks[ Disk ].Sectors = identify->Sectors28;
+ LOG("gATA_Disks[ Disk ].Sectors = 0x%x", gATA_Disks[ Disk ].Sectors);
+
if( gATA_Disks[ Disk ].Sectors / (2048*1024) )
Log("Disk %i: 0x%llx Sectors (%i GiB)", Disk,
gATA_Disks[ Disk ].Sectors, gATA_Disks[ Disk ].Sectors / (2048*1024));
// --- Scan Partitions ---
+ LOG("Reading MBR");
// Read Boot Sector
ATA_ReadDMA( Disk, 0, 1, mbr );
else // No? Just parse the MBR
ATA_ParseMBR(Disk);
+ LEAVE('i', 0);
return 1;
}
tMBR mbr;
Uint64 extendedLBA;
+ ENTER("iDisk", Disk);
+
// Read Boot Sector
ATA_ReadDMA( Disk, 0, 1, &mbr );
)
{
if( mbr.Parts[i].SystemID == 0xF || mbr.Parts[i].SystemID == 5 ) {
+ LOG("Extended Partition");
if(extendedLBA != 0) {
Warning("Disk %i has multiple extended partitions, ignoring rest", Disk);
continue;
extendedLBA = mbr.Parts[i].LBAStart;
continue;
}
+ LOG("Primary Partition");
gATA_Disks[Disk].NumPartitions ++;
continue;
}
}
}
+ LOG("gATA_Disks[Disk].NumPartitions = %i", gATA_Disks[Disk].NumPartitions);
// Create patition array
gATA_Disks[Disk].Partitions = malloc( gATA_Disks[Disk].NumPartitions * sizeof(tATA_Partition) );
extendedLBA = 0;
for( i = 0; i < 4; i ++ )
{
+ Log("mbr.Parts[%i].SystemID = 0x%02x", i, mbr.Parts[i].SystemID);
if( mbr.Parts[i].SystemID == 0 ) continue;
if( mbr.Parts[i].Boot == 0x0 || mbr.Parts[i].Boot == 0x80 ) // LBA 28
{
}
}
}
+
+ LEAVE('-');
}
/**
if(Name[0] < 'A' || Name[0] > 'A'+MAX_ATA_DISKS)
return NULL;
// Raw Disk
- if(Name[1] == '\0') return &gATA_Disks[Name[0]-'A'].Node;
+ if(Name[1] == '\0') {
+ if( gATA_Disks[Name[0]-'A'].Sectors == 0 )
+ return NULL;
+ return &gATA_Disks[Name[0]-'A'].Node;
+ }
// Partitions
if(Name[1] < '0' || '9' < Name[1]) return NULL;
int disk = Disk & 1;
Uint16 base;
+ ENTER("iDisk XAddress iCount pBuffer", Disk, Address, Count, Buffer);
+
// Check if the count is small enough
- if(Count > MAX_DMA_SECTORS) return 0;
+ if(Count > MAX_DMA_SECTORS) {
+ Warning("Passed too many sectors for a bulk DMA read (%i > %i)",
+ Count, MAX_DMA_SECTORS);
+ LEAVE('i');
+ return 0;
+ }
// Get exclusive access to the disk controller
LOCK( &giaATA_ControllerLock[ cont ] );
// Get Port Base
base = ATA_GetBasePort(Disk);
+ // Reset IRQ Flag
+ gaATA_IRQs[cont] = 0;
+
// Set up transfer
outb(base+0x01, 0x00);
if( Address > 0x0FFFFFFF ) // Use LBA48
outb(base+0x03, (Uint8) Address); // Low Addr
outb(base+0x04, (Uint8) (Address >> 8)); // Middle Addr
outb(base+0x05, (Uint8) (Address >> 16)); // High Addr
+
+ LOG("Starting Transfer");
+ #if START_BEFORE_CMD
+ // Start transfer
+ ATA_int_BusMasterWriteByte( cont << 3, 9 ); // Read and start
+ if( Address > 0x0FFFFFFF )
+ outb(base+0x07, HDD_DMA_R48); // Read Command (LBA48)
+ else
+ outb(base+0x07, HDD_DMA_R28); // Read Command (LBA28)
+ #else
if( Address > 0x0FFFFFFF )
outb(base+0x07, HDD_DMA_R48); // Read Command (LBA48)
else
outb(base+0x07, HDD_DMA_R28); // Read Command (LBA28)
-
- // Reset IRQ Flag
- gaATA_IRQs[cont] = 0;
-
// Start transfer
ATA_int_BusMasterWriteByte( cont << 3, 9 ); // Read and start
+ #endif
// Wait for transfer to complete
- while( gaATA_IRQs[cont] == 0 ) Threads_Yield();
+ //ATA_int_BusMasterWriteByte( (cont << 3) + 2, 0x4 );
+ while( gaATA_IRQs[cont] == 0 ) {
+ //Uint8 val = ATA_int_BusMasterReadByte( (cont << 3) + 2, 0x4 );
+ //LOG("val = 0x%02x", val);
+ Threads_Yield();
+ }
// Complete Transfer
ATA_int_BusMasterWriteByte( cont << 3, 0 ); // Write and stop
+ LOG("Transfer Completed & Acknowledged");
+
// Copy to destination buffer
memcpy( Buffer, gATA_Buffers[cont], Count*SECTOR_SIZE );
// Release controller lock
RELEASE( &giaATA_ControllerLock[ cont ] );
+ LEAVE('i', 1);
return 1;
}
// IRQ bit set for Primary Controller
val = ATA_int_BusMasterReadByte( 0x2 );
+ LOG("IRQ val = 0x%x", val);
if(val & 4) {
- //Log(" ATA_IRQHandlerPri: IRQ hit (val = 0x%x)", val);
+ LOG("IRQ hit (val = 0x%x)", val);
ATA_int_BusMasterWriteByte( 0x2, 4 );
gaATA_IRQs[0] = 1;
return ;
// IRQ bit set for Secondary Controller
val = ATA_int_BusMasterReadByte( 0xA );
if(val & 4) {
- //Log(" ATA_IRQHandlerSec: IRQ hit (val = 0x%x)", val);
+ LOG("IRQ hit (val = 0x%x)", val);
ATA_int_BusMasterWriteByte( 0xA, 4 );
gaATA_IRQs[1] = 1;
return ;
*
* By thePowersGang (John Hodge)
*/
+#define DEBUG 0
#include <common.h>
#include <iocache.h>
{
tIOCache_Ent *ent;
+ ENTER("pCache XSector pBuffer", Cache, Sector, Buffer);
+
// Sanity Check!
- if(!Cache || !Buffer)
+ if(!Cache || !Buffer) {
+ LEAVE('i', -1);
return -1;
+ }
// Lock
LOCK( &Cache->Lock );
if(Cache->CacheSize == 0) {
RELEASE( &Cache->Lock );
+ LEAVE('i', -1);
return -1;
}
memcpy(Buffer, ent->Data, Cache->SectorSize);
ent->LastAccess = now();
RELEASE( &Cache->Lock );
+ LEAVE('i', 1);
return 1;
}
// It's a sorted list, so as soon as we go past `Sector` we know
}
RELEASE( &Cache->Lock );
+ LEAVE('i', 0);
return 0;
}
case DRV_IOCTL_VERSION: *(int*)Data = 50; return 1;
case DRV_IOCTL_LOOKUP: return 0;
- case VIDEO_IOCTL_GETMODE: return 0; // Mode 0 only
- case VIDEO_IOCTL_SETMODE: return 0; // Ignored (Text Only ATM)
+ case VIDEO_IOCTL_GETSETMODE: return 0; // Mode 0 only
case VIDEO_IOCTL_FINDMODE: return 0; // Text Only!
case VIDEO_IOCTL_MODEINFO:
if( ((tVideo_IOCtl_Mode*)Data)->id != 0) return 0;
modeNum = mode.id;
gVT_Terminals[ ID ].RealWidth = mode.width;
gVT_Terminals[ ID ].RealHeight = mode.height;
- VFS_IOCtl( giVT_OutputDevHandle, VIDEO_IOCTL_SETMODE, &modeNum );
+ VFS_IOCtl( giVT_OutputDevHandle, VIDEO_IOCTL_GETSETMODE, &modeNum );
// Update current terminal ID
Log("Changed terminal from %i to %i", giVT_CurrentTerminal, ID);
*/
#define DEBUG 0
#include <common.h>
-#include <drvutil.h>
+#include <tpl_drv_disk.h>
// === CODE ===
Uint64 DrvUtil_ReadBlock(Uint64 Start, Uint64 Length, void *Buffer,
--- /dev/null
+/**
+ * \file apidoc_mainpage.h
+ * \brief API Documentation Home Page
+ * \author John Hodge (thePowersGang)
+ */
+
+/**
+ * \mainpage Acess 2 Kernel API Documentation
+ *
+ * \section intro Introduction
+ * These documents attempt to describe the standard Acess 2 (and hopefully
+ * future versions) Kernel mode API.
+ * The documentation covers filesystem drivers, binary formats and the
+ * various device driver interface standards.
+ *
+ * \section VFS
+ * The core of Acess is the VFS, or Virtual File System. The VFS abstracts
+ * away from the user the differences between different filesystems,
+ * network protocols and types of hardware.
+ * The core of the VFS is the concept of a VFS Node (represented by the
+ * ::tVFS_Node type). A node defines a file (either a normal file, directory
+ * or some device abstraction), it's attributes (size, flags, timestamps)
+ * and the functions used to access and modify it.
+ *
+ * \subsection filesystems Filesystem Drivers
+ * Acess filesystems register themselves with the VFS by calling
+ * ::VFS_AddDriver with a ::tVFS_Driver structure that defines the driver's
+ * name, flags and mount function.
+ * Filesystem drivers take the
+ *
+ * \section binfmt Binary Formats
+ * See binary.h
+ *
+ * \section drivers Device Drivers
+ * All Acess2 device drivers communicate with user-level (and other parts
+ * of the greater kernel) via the VFS. They register themselves in a similar
+ * way to how filesystem drivers do, however instead of registering with
+ * the VFS core, they register with a special filesystem driver called the
+ * DevFS (fs_devfs.h). DevFS exports the ::DevFS_AddDevice function that
+ * takes a ::tDevFS_Driver structure as an agument that defines the
+ * driver's name and the VFS node of it's root. This root is used to
+ * provide the user access to the driver's function via IOCtl calls and
+ * by Read/Write calls. Drivers are also able to expose a readonly buffer
+ * by using ProcDev, usually to provide state information (such as usage
+ * statistics and other misc information)
+ *
+ * The device driver interfaces are all based on the core specifcation
+ * in tpl_drv_common.h (Common Device Driver definitions).
+ * The following subsections define the various specific types of driver
+ * interfaces. These definitions only define the bare minimum of what the
+ * driver must implement, if the driver author so wants to, they can add
+ * IOCtl calls and/or files (where allowed by the type specifcation) to
+ * their device's VFS layout.
+ *
+ * \subsection drv_video Video Devices
+ * Video drivers are based on a framebuffer model (unless in 3D mode,
+ * which is not yet fully standardised, so should be ignored).
+ * The driver will contain only one VFS node, that exposes the video
+ * framebuffer (this may not be the true framebuffer, to allow for double-buffering)
+ * to the user. See the full documentation in tpl_drv_video.h for the
+ * complete specifcation.
+ */
-/*
+/**
+ * \file binary.h
+ * \brief Binary Loader Definitions
+ * \author John Hodge (thePowersGang)
*/
#ifndef _BINARY_H
#define _BINARY_H
// === TYPES ===
/**
- * \struct sBinary
* \brief Defines a binary file
+ *
+ * This structure defines and maintains the state of a binary during and
+ * after loading.
+ * Before the binary is loaded into memory (when it has just been returned
+ * from tBinaryType.Load) the \a Pages array will contain the file offsets
+ * to the page data in the \a Physical fields (or -1 for uninitialised
+ * data) and the \a Size fields define how much data is stored in-file
+ * for the page (to allow partial pages to be loaded from disk)
+ * Once the binary is loaded (NOTE: Drivers do not need to know about this,
+ * it is here for information only) the \a Physical fields now contain the
+ * physical addresses of the pages filled with the data. The \a Virtual
+ * fields contain the preferred virtual address of the pages (a given
+ * process may have these pages mapped to a different location).
*/
-typedef struct sBinary {
- struct sBinary *Next;
+typedef struct sBinary
+{
+ struct sBinary *Next; //!< Pointer used by the kernel
+ /**
+ * \brief True path of the file
+ * \note Used to uniquely identify the loaded binary to reduce in-memory
+ * duplication.
+ */
char *TruePath;
+ /**
+ * \brief Interpreter used to load the file
+ * \note This can be either requested by the individual file, or a per-driver option
+ */
char *Interpreter;
+ /**
+ * \brief Entrypoint of the binary (at requested base);
+ */
Uint Entry;
+ /**
+ * \brief File's requested load base
+ */
Uint Base;
- int NumPages;
+ /**
+ * \brief Number of times this binary has been mapped
+ */
int ReferenceCount;
+ /**
+ * \brief Number of pages defined in the file
+ */
+ int NumPages;
+ /**
+ * \brief Array of pages defined by this binary
+ * \note Contains \a NumPages entries
+ */
struct {
- Uint Physical;
- Uint Virtual;
- Uint16 Size, Flags;
+ /**
+ * \brief Physical address, or file offset
+ *
+ * Physical address of this page or, when the file is not yet
+ * loaded, this is a file offset (or -1 for uninitialised data)
+ */
+ tPAddr Physical;
+ tVAddr Virtual; //!< Virtual load address
+ Uint16 Size; //!< Number of bytes to load from the file
+ Uint16 Flags; //!< Load Flags
} Pages[];
-} tBinary;
+} tBinary;
/**
- * \struct sBinaryType
+ * \brief Binary type definition
+ *
+ * This structure is used to define a loader for a specific binary type
+ * so that the kernel's core binary loader can understand that type.
+ * The tBinaryType.Relocate and tBinaryType.GetSymbol need only be non-NULL
+ * if the binary type is to be used for kernel modules, otherwise it will
+ * only be able to load binaries for user space.
*/
-typedef struct sBinaryType {
+typedef struct sBinaryType
+{
+ /**
+ * \brief Pointer used by the kernel
+ * \note Should not be touched by the driver (initialise to NULL)
+ */
struct sBinaryType *Next;
+ /**
+ * \brief Identifying DWord
+ *
+ * If he first 32-bits of the file match this value (when ANDed with
+ * tBinaryType.Mask), this binary loader will be used to load the file.
+ */
Uint32 Ident;
- Uint32 Mask;
- char *Name;
+ Uint32 Mask; //!< Mask value for tBinaryType.Ident
+ char *Name; //!< Name of this executable type (for debug purpouses)
+ /**
+ * \brief Read a binary from a file
+ * \param FD VFS File handle to file to load
+ * \return Pointer to a ::tBinary that describes how to load the file
+ *
+ * This function reads a binary file and returns a ::tBinary pointer
+ * that tells the core binary loader how to read the data from the file
+ * and where to map it to.
+ */
tBinary *(*Load)(int FD);
+
+ /**
+ * \brief Prepares a mapped binary for execution at this address
+ * \param Base Binary loaded in memory
+ * \return Boolean Success
+ * \note This pointer can be NULL, but then the binary cannot be used
+ * to load a kernel module.
+ *
+ * tBinaryType.Relocate takes a binary that was loaded according to
+ * tBinaryType.Load and prepares it to run at the address it is
+ * loaded to, attempting to satisfy any external unresolved symbols
+ * required, if a symbol cannot be located, the function will return
+ * zero.
+ */
int (*Relocate)(void *Base);
+
+ /**
+ * \brief Gets a symbol's address from a loaded binary
+ * \note The binary pointed to by \a Base may not have been through
+ * tBinaryType.Relocate at this time, so the driver should
+ * accomodate this.
+ */
int (*GetSymbol)(void *Base, char *Name, Uint *Dest);
} tBinaryType;
+/**
+ * \brief Registers an interpreter path with the binary loader
+ * \param Path Path to the requested interpreter (need not be a "true" path)
+ * \return Pointer to the cached string
+ *
+ * Speeds up checking if the intepreter is loaded in the kernel by allowing
+ * the search to use pointer comparisons instead of string comparisons.
+ */
extern char *Binary_RegInterp(char *Path);
#endif
/**
* \}
*/
+// --- Interface Flags & Macros
+#define CLONE_VM 0x10
+
+// === Types ===
+typedef void (*tThreadFunction)(void*);
// === Kernel Export Macros ===
/**
/**
* \brief Get the physical address of \a VAddr
* \param VAddr Address of the page to get the physical address of
- * \return Physical page mapped at \A VAddr
+ * \return Physical page mapped at \a VAddr
*/
extern tPAddr MM_GetPhysAddr(tVAddr VAddr);
/**
+++ /dev/null
-/*
- * Acess2
- * Common Driver/Filesystem Helper Functions
- */
-
-#ifndef _DRVUTIL_H_
-#define _DRVUTIL_H_
-
-#include <common.h>
-
-// === TYPES ===
-typedef Uint (*tDrvUtil_Callback)(Uint64 Address, Uint Count, void *Buffer, Uint Argument);
-
-// === PROTOTYPES ===
-// --- Block IO Helpers ---
-extern Uint64 DrvUtil_ReadBlock(Uint64 Start, Uint64 Length, void *Buffer,
- tDrvUtil_Callback ReadBlocks, Uint64 BlockSize, Uint Argument);
-
-extern Uint64 DrvUtil_WriteBlock(Uint64 Start, Uint64 Length, void *Buffer,
- tDrvUtil_Callback ReadBlocks, tDrvUtil_Callback WriteBlocks,
- Uint64 BlockSize, Uint Argument);
-
-#endif
-/*
- * Acess 2
- * Device Filesystem (DevFS)
- * - vfs/fs/devfs.c
- */
/**
* \file fs_devfs.h
* \brief Acess Device Filesystem interface
+ * \author John Hodge (thePowersGang)
*/
#ifndef _FS_DEVFS_H
#define _FS_DEVFS_H
// === TYPES ===
/**
- * \brief DevFS Driver
+ * \brief DevFS driver definition
*/
-typedef struct sDevFS_Driver {
+typedef struct sDevFS_Driver
+{
struct sDevFS_Driver *Next; //!< Set to NULL by drivers (used internally)
- char *Name; //!< Name of the driver file/folder
+ char *Name; //!< Name of the driver file/folder (must be unique)
tVFS_Node RootNode; //!< Root node of driver
} tDevFS_Driver;
* \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
+ * \return Boolean success
*/
extern int DevFS_AddDevice(tDevFS_Driver *Dev);
* Acess2
* - SysFS Export Header
*/
+/**
+ * \file fs_sysfs.h
+ * \brief ProcDev/SysFS Interface
+ * \author John Hodge (thePowersGang)
+ *
+ *
+ */
#ifndef _FS_SYSFS_H_
#define _FS_SYSFS_H_
+/**
+ * \brief Registers a file in the SysFS tree
+ * \param Path Path relative to the SysFS root (no .. or .)
+ * \param Data File buffer address
+ * \param Length Length of the file buffer
+ * \return An ID number to refer to the file, or -1 on error
+ * \note \a Data must be maintained until ::SysFS_UpdateFile is called
+ * with a different buffer, or ::SysFS_RemoveFile is called.
+ */
extern int SysFS_RegisterFile(char *Path, char *Data, int Length);
+
+/**
+ * \brief Updates the size/pointer associated with a SysFD file
+ * \param ID Number returned by ::SysFS_Register
+ * \param Data New buffer address
+ * \param Length New length of the file
+ * \return Boolean Success
+ */
extern int SysFS_UpdateFile(int ID, char *Data, int Length);
+
+/**
+ * \brief Removes a file from the SysFS tree
+ * \param ID Number returned by ::SysFS_Register
+ */
extern int SysFS_RemoveFile(int ID);
#endif
-/*
- * Acess2
- * - Common Driver Interface
- */
/**
* \file tpl_drv_common.h
* \brief Common Driver Interface Definitions
+ * \author John Hodge (thePowersGang)
+ *
+ * \section Introduction
+ * There are two ways Acess drivers can communicate with userspace
+ * applications, both are through the VFS. The first is by exposing a
+ * device as a file buffer, the second is by sending commands via the
+ * ioctl() system call.
+ * All drivers in Acess must at least conform to the specifcation in this
+ * file (even if it is just implementing eTplDrv_IOCtl.DRV_IOCTL_TYPE and
+ * returning eTplDrv_Type.DRV_TYPE_NULL, however, doing so is discouraged)
+ *
+ * \section ioctls Core IOCtl calls
+ * As said, the core Acess driver specifcation defines specific IOCtl calls
+ * that all drivers should implement. The four core IOCtls (defined in
+ * ::eTplDrv_IOCtl) allow another binary (wether it be a user-mode application
+ * or another driver) to tell what type of device a driver provides, the
+ * basic identifcation of the driver (4 character ID and BCD version number)
+ * and be able to use externally standardised calls that may not have
+ * standardised call numbers.
+ * NOTE: All ioctl calls WILL return -1 if the driver ran into an error
+ * of its own fault while executing the call. If the user was at fault
+ * (e.g. by passing a bad buffer) the call will return -2.
+ *
+ * \section types Driver Types
+ * When the eTplDrv_IOCtl.DRV_IOCTL_TYPE call is made, the driver should
+ * return the relevant entry in the ::eTplDrv_Type enumeration that describes
+ * what sub-specifcation (and hence, what device type) it implements.
+ * These device types are described in their own files, which are liked
+ * from their entries in ::eTplDrv_Type.
*/
#ifndef _TPL_COMMON_H
#define _TPL_COMMON_H
* \brief Common IOCtl Calls
*/
enum eTplDrv_IOCtl {
- /// \brief Driver Type - Return an ::eTplDrv_Type value
+ /**
+ * ioctl(...)
+ * \brief Get driver type
+ * \return The relevant entry from ::eTplDrv_Type
+ */
DRV_IOCTL_TYPE,
- /// \brief Get driver identifier - (char *dest[4])
+
+ /**
+ * ioctl(..., char *dest[4])
+ * \brief Get driver identifier string
+ * \return 0 on no error
+ *
+ * This call sets the 4-byte array \a dest to the drivers 4-byte
+ * identifier. This identifier must be unique to the driver series.
+ */
DRV_IOCTL_IDENT,
- /// \brief Get driver version - (int *ver)
+
+ /**
+ * ioctl(...)
+ * \brief Get driver version number
+ * \return 24-bit BCD version number (2.2)
+ *
+ * This call returns the 6-digit (2 major, 2 minor, 2 patch) version number
+ * of the driver.
+ */
DRV_IOCTL_VERSION,
- /// \brief Get a IOCtl from a symbolic name
+
+ /**
+ * ioctl(..., char *name)
+ * \brief Get a IOCtl call ID from a symbolic name
+ * \return ID number of the call, or 0 if not found
+ *
+ * This call allows user applications to not need to know the ID numbers
+ * of this driver's IOCtl calls by taking a string and returning the
+ * IOCtl call number associated with that method name.
+ */
DRV_IOCTL_LOOKUP
};
+//! \brief eTplDrv_IOCtl.DRV_IOCTL_LOOKUP names for the core IOCtls
+//! These are the official lookup names of the core calls
#define DRV_IOCTLNAMES "type", "ident", "version", "lookup"
/**
enum eTplDrv_Type {
DRV_TYPE_NULL, //!< NULL Type - Custom Interface
DRV_TYPE_MISC, //!< Miscelanious Compilant - Supports the core calls
- DRV_TYPE_TERMINAL, //!< Terminal
- DRV_TYPE_VIDEO, //!< Video - LFB
+ DRV_TYPE_TERMINAL, //!< Terminal - see tpl_drv_terminal.h
+ DRV_TYPE_VIDEO, //!< Video - see tpl_drv_video.h
DRV_TYPE_SOUND, //!< Audio
- DRV_TYPE_DISK, //!< Disk
- DRV_TYPE_KEYBOARD, //!< Keyboard
+ DRV_TYPE_DISK, //!< Disk - see tpl_drv_disk.h
+ DRV_TYPE_KEYBOARD, //!< Keyboard - see tpl_drv_keyboard.h
DRV_TYPE_MOUSE, //!< Mouse
DRV_TYPE_JOYSTICK, //!< Joystick / Gamepad
- DRV_TYPE_NETWORK //!< Network Device
+ DRV_TYPE_NETWORK //!< Network Device - see tpl_drv_network.h
};
#endif
--- /dev/null
+/**\r
+ * \file tpl_drv_disk.h\r
+ * \brief Disk Driver Interface Definitions\r
+ * \author John Hodge (thePowersGang)\r
+ * \r
+ * \section dirs VFS Layout\r
+ * Disk drivers have a flexible directory layout. The root directory can\r
+ * contain subdirectories, with the only conditions being that all nodes\r
+ * must support ::eTplDrv_IOCtl with DRV_IOCTL_TYPE returning DRV_TYPE_DISK.\r
+ * And all file nodes representing disk devices (or partitions) and implemeting\r
+ * ::eTplDisk_IOCtl fully\r
+ * \r
+ * \section files Files\r
+ * When a read or write occurs on a normal file in the disk driver it will\r
+ * read/write the represented device. The accesses need not be aligned to\r
+ * the block size, however aligned reads/writes should be handled specially\r
+ * to improve speed (this can be aided by using ::DrvUtil_ReadBlock and\r
+ * ::DrvUtil_WriteBlock)\r
+ */\r
+#ifndef _TPL_DRV_DISK_H\r
+#define _TPL_DRV_DISK_H\r
+\r
+#include <tpl_drv_common.h>\r
+\r
+/**\r
+ * \enum eTplDisk_IOCtl\r
+ * \brief Common Disk IOCtl Calls\r
+ * \extends eTplDrv_IOCtl\r
+ */\r
+enum eTplDisk_IOCtl {\r
+ /**\r
+ * ioctl(..., void)\r
+ * \brief Get the block size\r
+ * \return Size of a hardware block for this device\r
+ */\r
+ DISK_IOCTL_GETBLOCKSIZE = 4\r
+};\r
+\r
+/**\r
+ * \brief IOCtl name strings\r
+ */\r
+#define DRV_DISK_IOCTLNAMES "get_block_size"\r
+\r
+/**\r
+ * \brief Callback function type used by DrvUtil_ReadBlock and DrvUtil_WriteBlock\r
+ * \param Address Zero based block number to read\r
+ * \param Count Number of blocks to read\r
+ * \param Buffer Destination for read blocks\r
+ * \param Argument Argument provided in ::DrvUtil_ReadBlock and ::DrvUtil_WriteBlock\r
+ */\r
+typedef Uint (*tDrvUtil_Callback)(Uint64 Address, Uint Count, void *Buffer, Uint Argument);\r
+\r
+/**\r
+ * \brief Reads a range from a block device using aligned reads\r
+ * \param Start Base byte offset\r
+ * \param Length Number of bytes to read\r
+ * \param Buffer Destination for read data\r
+ * \param ReadBlocks Callback function to read a sequence of blocks\r
+ * \param BlockSize Size of an individual block\r
+ * \param Argument An argument to pass to \a ReadBlocks\r
+ * \return Number of bytes read\r
+ */\r
+extern Uint64 DrvUtil_ReadBlock(Uint64 Start, Uint64 Length, void *Buffer,\r
+ tDrvUtil_Callback ReadBlocks, Uint64 BlockSize, Uint Argument);\r
+/**\r
+ * \brief Writes a range to a block device using aligned writes\r
+ * \param Start Base byte offset\r
+ * \param Length Number of bytes to write\r
+ * \param Buffer Destination for read data\r
+ * \param ReadBlocks Callback function to read a sequence of blocks\r
+ * \param WriteBlocks Callback function to write a sequence of blocks\r
+ * \param BlockSize Size of an individual block\r
+ * \param Argument An argument to pass to \a ReadBlocks and \a WriteBlocks\r
+ * \return Number of bytes written\r
+ */\r
+extern Uint64 DrvUtil_WriteBlock(Uint64 Start, Uint64 Length, void *Buffer,\r
+ tDrvUtil_Callback ReadBlocks, tDrvUtil_Callback WriteBlocks,\r
+ Uint64 BlockSize, Uint Argument);\r
+\r
+#endif\r
/**\r
* \file tpl_drv_keyboard.h\r
* \brief Keyboard Driver Interface Definitions\r
-*/\r
+ * \author John Hodge (thePowersGang)\r
+ * \r
+ * \section dirs VFS Layout\r
+ * Keyboard drivers consist of only a single node, which is a normal file\r
+ * node with a size of zero. All reads and writes to this node are ignored\r
+ * (tVFS_Node.Read and tVFS_Node.Write are NULL)\r
+ */\r
#ifndef _TPL_KEYBOARD_H\r
#define _TPL_KEYBOARD_H\r
\r
* \extends eTplDrv_IOCtl\r
*/\r
enum eTplKeyboard_IOCtl {\r
- //! \brief Get/Set Repeat Rate - (int Rate)\r
+ /**\r
+ * ioctl(..., int *Rate)\r
+ * \brief Get/Set Repeat Rate\r
+ * \param Rate New repeat rate (pointer)\r
+ * \return Current/New Repeat rate\r
+ * \r
+ * Gets/Set the repeat rate (actually the time in miliseconds between\r
+ * repeats) of a held down key.\r
+ * If the rate is set to zero, repeating will be disabled.\r
+ */\r
KB_IOCTL_REPEATRATE = 4,\r
- //! \brief Get/Set Repeat Delay - (int Delay)\r
+ \r
+ /**\r
+ * ioctl(..., int *Delay)\r
+ * \brief Get/Set Repeat Delay\r
+ * \param Delay New repeat delay (pointer)\r
+ * \return Current/New repeat delay\r
+ * \r
+ * Gets/Set the time in miliseconds before a key starts repeating\r
+ * after a key is pressed.\r
+ * Setting the delay to a negative number will cause the function to\r
+ * return -1\r
+ */\r
KB_IOCTL_REPEATDELAY,\r
- //! \brief Sets the callback\r
+ \r
+ \r
+ /**\r
+ * ioctl(..., tKeybardCallback *Callback)\r
+ * \brief Sets the callback\r
+ * \note Can be called from kernel mode only\r
+ * \r
+ * Sets the function to be called when a key event occurs (press, release\r
+ * or repeat). This function pointer must be in kernel mode (although,\r
+ * kernel->user or kernel->ring3driver abstraction functions can be used)\r
+ */\r
KB_IOCTL_SETCALLBACK\r
};\r
\r
/**\r
* \brief Callback type for KB_IOCTL_SETCALLBACK\r
+ * \param Key Unicode character code for the pressed key (with bit 31\r
+ * set if the key is released)\r
*/\r
typedef void (*tKeybardCallback)(Uint32 Key);\r
\r
/**\r
* \brief Symbolic key codes\r
+ * \r
+ * These key codes represent non-pritable characters and are placed above\r
+ * the Unicode character space.\r
+ * If the using driver recieves a key code with the 31st bit set, it means\r
+ * that that key has been released.\r
*/\r
enum eTplKeyboard_KeyCodes {\r
- KEY_ESC = 0x1B,\r
+ KEY_ESC = 0x1B, //!< Escape Character\r
\r
- KEY_NP_MASK = 0x40000000, //End of ASCII Range\r
+ KEY_NP_MASK = 0x40000000, //! Mask for non-printable characters\r
\r
+ /**\r
+ * \name Special Keys\r
+ * \brief These keys are usually used on their own\r
+ * \{\r
+ */\r
KEY_CAPSLOCK,\r
KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT,\r
KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, \r
KEY_KPHOME, KEY_KPUP, KEY_KPPGUP, KEY_KPLEFT, KEY_KP5, KEY_KPRIGHT,\r
KEY_KPEND, KEY_KPDOWN, KEY_KPPGDN, KEY_KPINS, KEY_KPDEL,\r
KEY_WIN, KEY_MENU,\r
+ /**\r
+ * \}\r
+ */\r
\r
// Modifiers\r
+ /**\r
+ * \name Modifiers\r
+ * \brief These keye usually alter the character stream sent to the user\r
+ * \{\r
+ */\r
KEY_MODIFIERS = 0x60000000,\r
KEY_LCTRL, KEY_RCTRL,\r
KEY_LALT, KEY_RALT,\r
KEY_LSHIFT, KEY_RSHIFT,\r
- \r
- KEY_KEYUP = 0xFF\r
+ /**\r
+ * \}\r
+ */\r
};\r
\r
\r
/**\r
* \file tpl_drv_network.h\r
* \brief Network Interface Driver Interface Definitions\r
-*/\r
+ * \r
+ * \section dirs VFS Layout\r
+ * All network drivers must have the following basic VFS structure\r
+ * The root of the driver will only contain files that are named from zero\r
+ * upwards that represent the present network adapters that this driver\r
+ * controls. All VFS nodes must implement ::eTplDrv_IOCtl with\r
+ * DRV_IOCTL_TYPE returning DRV_TYPE_NETWORK.\r
+ * The adapter nodes must also implement ::eTplNetwork_IOCtl fully\r
+ * (unless it is noted in the ::eTplNetwork_IOCtl documentation that a\r
+ * call is optional)\r
+ * \r
+ * \section files Adapter Files\r
+ * \subsection Reading\r
+ * When an adapter file is read from, the driver will block the reading\r
+ * thread until a packet arrives (if there is not already an unhandled\r
+ * packet in the queue) this will then be read into the destination buffer.\r
+ * If the packet does not fit in the buffer, the end of it is discarded.\r
+ * Likewise, if the packet does not completely fill the buffer, the call\r
+ * will still read to the buffer and then return the size of the packet.\r
+ * \subsection Writing\r
+ * When an adapter is written to, the data written is encoded as a packet\r
+ * and sent, if the data is not the correct size to be sent (if the packet\r
+ * is too small, or if it is too large) -1 should be returned and the packet\r
+ * will not be sent.\r
+ */\r
#ifndef _TPL_NETWORK_H\r
#define _TPL_NETWORK_H\r
\r
/**\r
* ioctl(..., Uint8 *MAC[6])\r
* \brief Get the MAC address of the interface\r
+ * \return 1 on success, 0 if the file is the root, -1 on error\r
+ * \r
+ * Copies the six byte Media Access Control (MAC) address of the\r
+ * adapter to the \a MAC array.\r
*/\r
NET_IOCTL_GETMAC = 4\r
};\r
\r
+/**\r
+ * \brief IOCtl name strings for use with eTplDrv_IOCtl.DRV_IOCTL_LOOKUP\r
+ */\r
#define DRV_NETWORK_IOCTLNAMES "get_mac_addr"\r
\r
#endif\r
#include <tpl_drv_common.h>\r
\r
/**\r
- * \enum eTplTerminal_IOCtl\r
* \brief Common Terminal IOCtl Calls\r
* \extends eTplDrv_IOCtl\r
*/\r
/**\r
* ioctl(..., int *mode)\r
* \brief Get/Set the current video mode type\r
- * see ::eTplTerminal_Modes\r
- * \note If the mode is set the mode is changed at this call\r
+ * \param mode Pointer to an integer with the new mode number (or NULL)\r
+ * If \a mode is non-NULL the current terminal mode is changed/updated\r
+ * to the mode indicated by \a *mode\r
+ * \note See ::eTplTerminal_Modes\r
+ * \return Current/new terminal mode\r
*/\r
TERM_IOCTL_MODETYPE = 4,\r
\r
/**\r
* ioctl(..., int *width)\r
* \brief Get/set the display width\r
- * \param width Pointer to an integer containing the new width\r
- * \return Current width\r
+ * \param width Pointer to an integer containing the new width (or NULL)\r
+ * \return Current/new width\r
* \r
- * Set `width` to NULL to just return the current width\r
+ * If \a width is non-NULL the current width is updated (but is not\r
+ * applied until ::TERM_IOCTL_MODETYPE is called with \a mode non-NULL.\r
*/\r
TERM_IOCTL_WIDTH,\r
\r
* \param height Pointer to an integer containing the new height\r
* \return Current height\r
* \r
- * Set \a height to NULL to just return the current height\r
+ * If \a height is non-NULL the current height is updated (but is not\r
+ * applied until ::TERM_IOCTL_MODETYPE is called with a non-NULL \a mode.\r
*/\r
TERM_IOCTL_HEIGHT,\r
\r
/**\r
* ioctl(..., tTerm_IOCtl_Mode *info)\r
- * \brief Queries the current driver about it's modes\r
- * \param info A pointer to a ::tTerm_IOCtl_Mode with .ID set to the mode index\r
+ * \brief Queries the current driver about it's native modes\r
+ * \param info A pointer to a ::tTerm_IOCtl_Mode with \a ID set to\r
+ * the mode index (or NULL)\r
* \return Number of modes\r
* \r
- * \a info can be NULL\r
+ * If \a info is NULL, the number of avaliable vative display modes\r
+ * is returned. These display modes will have sequential ID numbers\r
+ * from zero up to this value.\r
+ * \r
+ * \note The id field of \a info is not for use with ::TERM_IOCTL_MODETYPE\r
+ * This field is just for indexing the mode to get its information.\r
*/\r
TERM_IOCTL_QUERYMODE\r
};\r
\r
-typedef struct sTerm_IOCtl_Mode tTerm_IOCtl_Mode;\r
-\r
/**\r
* \brief Virtual Terminal Mode\r
* Describes a VTerm mode to the caller of ::TERM_IOCTL_QUERYMODE\r
*/\r
-struct sTerm_IOCtl_Mode\r
+typedef struct sTerm_IOCtl_Mode\r
{\r
short ID; //!< Zero Based index of mode\r
short DriverID; //!< Driver's ID number (from ::tVideo_IOCtl_Mode)\r
unsigned bText: 1; //!< Text Mode marker\r
unsigned unused: 7;\r
};\r
-};\r
+} tTerm_IOCtl_Mode;\r
\r
/**\r
* \brief Terminal Modes\r
*/\r
TERM_MODE_OPENGL,\r
\r
+ /**\r
+ * \brief Number of terminal modes\r
+ */\r
NUM_TERM_MODES\r
};\r
\r
* \extends eTplDrv_IOCtl\r
*/\r
enum eTplVideo_IOCtl {\r
- //! \brief Set Mode - (int mode)\r
- VIDEO_IOCTL_SETMODE = 4,\r
- //! \brief Get Mode - (int *mode)\r
- VIDEO_IOCTL_GETMODE,\r
- //! \brief Find a matching mode - (tVideo_IOCtl_Mode *info)\r
+ /**\r
+ * ioctl(..., int *mode)\r
+ * \brief Get/Set Mode\r
+ * \return Current mode ID or -1 on error\r
+ * \r
+ * If \a mode is non-NULL, the current video mode is set to \a *mode.\r
+ * This updated ID is then returned to the user.\r
+ */\r
+ VIDEO_IOCTL_GETSETMODE = 4,\r
+ \r
+ /**\r
+ * ioctl(..., tVideo_IOCtl_Mode *info)\r
+ * \brief Find a matching mode\r
+ * \return 1 if a mode was found, 0 otherwise\r
+ * \r
+ * Using avaliable modes matching the \a bpp and \a flags fields\r
+ * set the \a id field to the mode id of the mode with the closest\r
+ * \a width and \a height.\r
+ */\r
VIDEO_IOCTL_FINDMODE,\r
- //! \brief Get mode info - (tVideo_IOCtl_Mode *info)\r
+ \r
+ /**\r
+ * ioctl(..., tVideo_IOCtl_Mode *info)\r
+ * \brief Get mode info\r
+ * \return 1 if the mode exists, 0 otherwise\r
+ * \r
+ * Set \a info's fields to the mode specified by the \a id field.\r
+ */\r
VIDEO_IOCTL_MODEINFO,\r
- //! \brief Sets the cursor position (tVideo_IOCtl_Pos *pos)\r
+ \r
+ /**\r
+ * ioctl(..., tVideo_IOCtl_Pos *pos)\r
+ * \brief Sets the cursor position\r
+ * \return Boolean success\r
+ * \r
+ * Set the text mode cursor position (if it is supported)\r
+ * If the \a pos is set to (-1,-1) the cursor is hidden, otherwise\r
+ * \a pos MUST be within the current screen size (as given by the\r
+ * current mode's tVideo_IOCtl_Mode.width and tVideo_IOCtl_Mode.height\r
+ * fields).\r
+ */\r
VIDEO_IOCTL_SETCURSOR,\r
- //! \brief Request access to Framebuffer - (void *dest), Return Boolean Success\r
+ \r
+ /**\r
+ * ioctl(..., tVAddr MapTo)\r
+ * \brief Request access to Framebuffer\r
+ * \return Boolean Success\r
+ * \r
+ * Requests the driver to allow the user direct access to the\r
+ * framebuffer by mapping it to the supplied address.\r
+ * If the driver does not allow this boolean FALSE (0) is returned,\r
+ * else if the call succeeds (and the framebuffer ends up mapped) boolean\r
+ * TRUE (1) is returned.\r
+ */\r
VIDEO_IOCTL_REQLFB\r
};\r
\r
/**\r
* \brief Mode Structure used in IOCtl Calls\r
+ * \r
+ * Defines a video mode supported by (or requested of) this driver (depending\r
+ * on what ioctl call is used)\r
*/\r
-struct sVideo_IOCtl_Mode {\r
- short id; //!< Mide ID\r
+typedef struct sVideo_IOCtl_Mode\r
+{\r
+ short id; //!< Mode ID\r
Uint16 width; //!< Width\r
Uint16 height; //!< Height\r
- Uint8 bpp; //!< Bits per Pixel\r
+ Uint8 bpp; //!< Bits per Unit (Character or Pixel, depending on \a flags)\r
Uint8 flags; //!< Mode Flags\r
-};\r
-typedef struct sVideo_IOCtl_Mode tVideo_IOCtl_Mode; //!< Mode Type\r
+} tVideo_IOCtl_Mode;\r
\r
//! \name Video Mode flags\r
//! \{\r
/**\r
* \brief Describes a position in the video framebuffer\r
*/\r
-typedef struct sVideo_IOCtl_Pos tVideo_IOCtl_Pos;\r
-struct sVideo_IOCtl_Pos {\r
+typedef struct sVideo_IOCtl_Pos\r
+{\r
Sint16 x; //!< X Coordinate\r
Sint16 y; //!< Y Coordinate\r
-};\r
+} tVideo_IOCtl_Pos;\r
\r
/**\r
* \brief Virtual Terminal Representation of a character\r
*/\r
-typedef struct sVT_Char tVT_Char;\r
-struct sVT_Char {\r
+typedef struct sVT_Char\r
+{\r
Uint32 Ch; //!< UTF-32 Character\r
union {\r
struct {\r
};\r
Uint32 Colour; //!< Compound colour for ease of access\r
};\r
-};\r
+} tVT_Char;\r
\r
/**\r
* \name Basic builtin colour definitions\r
extern int giVT_CharHeight;\r
/**\r
* \fn void VT_Font_Render(Uint32 Codepoint, void *Buffer, int Pitch, Uint32 BGC, Uint32 FGC)\r
- * \brief Renders a character to a buffer\r
+ * \brief Driver helper that renders a character to a buffer\r
* \param Codepoint Unicode character to render\r
* \param Buffer Buffer to render to (32-bpp)\r
* \param Pitch Number of DWords per line\r
* \param BGC 32-bit Background Colour\r
* \param FGC 32-bit Foreground Colour\r
+ * \r
+ * This function is provided to help video drivers to support a simple\r
+ * text mode by keeping the character rendering abstracted from the driver,\r
+ * easing the driver development and reducing code duplication.\r
*/\r
extern void VT_Font_Render(Uint32 Codepoint, void *Buffer, int Pitch, Uint32 BGC, Uint32 FGC);\r
/**\r
* \fn Uint32 VT_Colour12to24(Uint16 Col12)\r
* \brief Converts a colour from 12bpp to 32bpp\r
* \param Col12 12-bpp input colour\r
- * \return Expanded 32-bpp (24-bit colour) version of \a Col12\r
+ * \return Expanded 32-bpp (24-bit colour) version of \a Col12\r
*/\r
extern Uint32 VT_Colour12to24(Uint16 Col12);\r
\r
#include <common.h>
-//! \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
-//! \}
-
/**
* \name VFS Node Flags
* \{
/**
* \brief VFS Node
+ * \todo Complete / Finalise
*/
typedef struct sVFS_Node {
Uint64 Inode; //!< Inode ID
int NumACLs; //!< Number of ACL entries
tVFS_ACL *ACLs; //!< ACL Entries
- //! Reference the node
+ /**
+ * \brief Reference the node
+ * \param Node Pointer to this node
+ */
void (*Reference)(struct sVFS_Node *Node);
- //! Close (dereference) the node
+ /**
+ * \brief Close (dereference) the node
+ * \param Node Pointer to this node
+ */
void (*Close)(struct sVFS_Node *Node);
- //! Send an IO Control
+
+ /**
+ * \brief Send an IO Control
+ * \param Node Pointer to this node
+ * \param Id IOCtl call number
+ * \param Data Pointer to data to pass to the driver
+ * \return Implementation defined
+ */
int (*IOCtl)(struct sVFS_Node *Node, int Id, void *Data);
- //! \brief Read from the file
+ /**
+ * \brief Read from the file
+ * \param Node Pointer to this node
+ * \param Offset Byte offset in the file
+ * \param Length Number of bytes to read
+ * \param Buffer Destination for read data
+ * \return Number of bytes read
+ */
Uint64 (*Read)(struct sVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
- //! \brief Write to the file
+ /**
+ * \brief Write to the file
+ * \param Node Pointer to this node
+ * \param Offset Byte offser in the file
+ * \param Length Number of bytes to write
+ * \param Buffer Source of written data
+ * \return Number of bytes read
+ */
Uint64 (*Write)(struct sVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
- //! \brief Find an directory entry by name
- //! \note The node returned must be accessable until ::tVFS_Node.Close is called
+ /**
+ * \brief Find an directory entry by name
+ * \param Node Pointer to this node
+ * \param Name Name of the file wanted
+ * \return Pointer to the requested node or NULL if it cannot be found
+ * \note The node returned must be accessable until ::tVFS_Node.Close
+ * is called and ReferenceCount reaches zero.
+ */
struct sVFS_Node *(*FindDir)(struct sVFS_Node *Node, char *Name);
- //! \brief Read from a directory
- //! \note MUST return a heap address
+ /**
+ * \brief Read from a directory
+ * \param Node Pointer to this node
+ * \param Pos Offset in the directory
+ * \return Pointer to the name of the item on the heap (will be freed
+ * by the caller). If the directory end has been reached, NULL
+ * will be returned.
+ * If an item is required to be skipped either &::NULLNode,
+ * ::VFS_SKIP or ::VFS_SKIPN(0...1023) will be returned.
+ */
char *(*ReadDir)(struct sVFS_Node *Node, int Pos);
- //! \brief Create a node in a directory
+ /**
+ * \brief Create a node in a directory
+ * \param Node Pointer to this node
+ * \param Name Name of the new child
+ * \param Flags Flags to apply to the new child (directory or symlink)
+ * \return Boolean success
+ */
int (*MkNod)(struct sVFS_Node *Node, char *Name, Uint Flags);
- //! \brief Relink (Rename/Remove) a file/directory
+ /**
+ * \brief Relink (Rename/Remove) a file/directory
+ * \param Node Pointer to this node
+ * \param OldName Name of the item to move/delete
+ * \param NewName New name (or NULL if unlinking is wanted)
+ * \return Boolean Success
+ */
int (*Relink)(struct sVFS_Node *Node, char *OldName, char *NewName);
-
- //!< \todo Complete
} tVFS_Node;
/**
-/*
- * Acess 2
- * vfs_ext.h
- * - Exported Symbols from the VFS
+/**
+ * \file vfs_ext.h
+ * \brief Exported VFS Definitions
+ * \author John Hodge (thePowersGang)
*/
#ifndef _VFS_EXT_H
#define _VFS_EXT_H
// === CONSTANTS ===
+//! maximum size of a Memory Path generated by VFS_GetMemPath
#define VFS_MEMPATH_SIZE (3 + (BITS/8)*2)
+/**
+ * \name Flags for VFS_Open
+ * \{
+ */
+//! Open for execution
#define VFS_OPENFLAG_EXEC 0x01
+//! Open for reading
#define VFS_OPENFLAG_READ 0x02
+//! Open for writing
#define VFS_OPENFLAG_WRITE 0x04
+//! Do not resolve the final symbolic link
#define VFS_OPENFLAG_NOLINK 0x40
+//! Open as a user
#define VFS_OPENFLAG_USER 0x80
+/**
+ * \}
+ */
+//! Marks a VFS handle as belonging to the kernel
#define VFS_KERNEL_FLAG 0x40000000
-#define SEEK_SET 1
-#define SEEK_CUR 0
-#define SEEK_END -1
+/**
+ * \brief VFS_Seek directions
+ */
+enum eVFS_SeekDirs
+{
+ SEEK_SET = 1, //!< Set the current file offset
+ SEEK_CUR = 0, //!< Seek relative to the current position
+ SEEK_END = -1 //!< Seek from the end of the file backwards
+};
+
+/**
+ * \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
+/**
+ * \}
+ */
// -- System Call Structures ---
/**
unsigned Inv: 1; //!< Invert Permissions
unsigned Perms: 31; //!< Permission Flags
};
-} tVFS_ACL;
+} tVFS_ACL;
-struct s_sysFInfo {
- Uint uid, gid;
- Uint flags;
- Uint64 size;
- Sint64 atime;
- Sint64 mtime;
- Sint64 ctime;
- int numacls;
- tVFS_ACL acls[];
-};
+/**
+ * \brief SYS_FINFO structure
+ */
+typedef struct sFInfo
+{
+ Uint uid; //!< Owning User ID
+ Uint gid; //!< Owning Group ID
+ Uint flags; //!< File flags
+ Uint64 size; //!< File Size
+ Sint64 atime; //!< Last Accessed time
+ Sint64 mtime; //!< Last modified time
+ Sint64 ctime; //!< Creation time
+ int numacls; //!< Total number of ACL entries
+ tVFS_ACL acls[]; //!< ACL buffer (size is passed in the \a MaxACLs argument to VFS_FInfo)
+} tFInfo;
// === FUNCTIONS ===
+/**
+ * \brief Initialise the VFS (called by system.c)
+ * \return Boolean Success
+ */
extern int VFS_Init();
-extern int VFS_Open(char *Path, Uint Flags);
+/**
+ * \brief Open a file
+ * \param Path Absolute or relative path to the file
+ * \param Mode Flags defining how to open the file
+ * \return VFS Handle (an integer) or -1 if an error occured
+ */
+extern int VFS_Open(char *Path, Uint Mode);
+/**
+ * \brief Close a currently open file
+ * \param FD Handle returned by ::VFS_Open
+ */
extern void VFS_Close(int FD);
+/**
+ * \brief Get file information from an open file
+ * \param FD File handle returned by ::VFS_Open
+ * \param Dest Destination for the read information
+ * \param MaxACLs Number of ACL slots allocated in the \a Dest structure
+ * \return Boolean Success
+ *
+ * If the \a NumACLs is smaller than the number of ACLs the node has, only
+ * \a NumACLs will be copied into \a Dest, but the tFInfo.numacls field
+ * will be set to the true ammount of ACLs. It is up to the user to do with
+ * this information how they like.
+ */
+extern int VFS_FInfo(int FD, tFInfo *Dest, int MaxACLs);
+/**
+ * \brief Gets the permissions appling to a user/group.
+ * \param FD File handle returned by ::VFS_Open
+ * \param Dest ACL information structure to edit
+ * \return Boolean success
+ *
+ * This function sets the tVFS_ACL.Inv and tVFS_ACL.Perms fields to what
+ * permissions the user/group specied in tVFS_ACL.ID has on the file.
+ */
+extern int VFS_GetACL(int FD, tVFS_ACL *Dest);
+/**
+ * \brief Changes the user's current working directory
+ * \param Dest New working directory (either absolute or relative to the current)
+ * \return Boolean Success
+ */
+extern int VFS_ChDir(char *Dest);
+/**
+ * \brief Change the current virtual root for the user
+ * \param New New virtual root (same as ::VFS_ChDir but cannot go
+ * above the current virtual root)
+ * \return Boolean success
+ */
+extern int VFS_ChRoot(char *New);
+
+/**
+ * \brief Change the location of the current file pointer
+ * \param FD File handle returned by ::VFS_Open
+ * \param Offset Offset within the file to go to
+ * \param Whence A direction from ::eVFS_SeekDirs
+ * \return Boolean success
+ */
extern int VFS_Seek(int FD, Sint64 Offset, int Direction);
+/**
+ * \brief Returns the current file pointer
+ * \param FD File handle returned by ::VFS_Open
+ * \return Current file position
+ */
extern Uint64 VFS_Tell(int FD);
+/**
+ * \brief Reads data from a file
+ * \param FD File handle returned by ::VFS_Open
+ * \param Length Number of bytes to read from the file
+ * \param Buffer Destination of read data
+ * \return Number of read bytes
+ */
extern Uint64 VFS_Read(int FD, Uint64 Length, void *Buffer);
+/**
+ * \brief Writes data to a file
+ * \param FD File handle returned by ::VFS_Open
+ * \param Length Number of bytes to write to the file
+ * \param Buffer Source of written data
+ * \return Number of bytes written
+ */
extern Uint64 VFS_Write(int FD, Uint64 Length, void *Buffer);
+/**
+ * \brief Reads from a specific offset in the file
+ * \param FD File handle returned by ::VFS_Open
+ * \param Offset Byte offset in the file
+ * \param Length Number of bytes to read from the file
+ * \param Buffer Source of read data
+ * \return Number of bytes read
+ */
extern Uint64 VFS_ReadAt(int FD, Uint64 Offset, Uint64 Length, void *Buffer);
+/**
+ * \brief Writes to a specific offset in the file
+ * \param FD File handle returned by ::VFS_Open
+ * \param Offset Byte offset in the file
+ * \param Length Number of bytes to write to the file
+ * \param Buffer Source of written data
+ * \return Number of bytes written
+ */
extern Uint64 VFS_WriteAt(int FD, Uint64 Offset, Uint64 Length, void *Buffer);
+/**
+ * \brief Sends an IOCtl request to the driver
+ * \param FD File handle returned by ::VFS_Open
+ * \param ID IOCtl call ID (driver specific)
+ * \param Buffer Data pointer to send to the driver
+ * \return Driver specific response
+ */
extern int VFS_IOCtl(int FD, int ID, void *Buffer);
-extern void VFS_GetMemPath(void *Base, Uint Length, char *Dest);
+/**
+ * \brief Creates a VFS Memory path from a pointer and size
+ * \param Dest Destination for the created path
+ * \param Base Base of the memory file
+ * \param Length Length of the memory buffer
+ * \note A maximum of VFS_MEMPATH_SIZE bytes will be required in \a Dest
+ */
+extern void VFS_GetMemPath(char *Dest, void *Base, Uint Length);
+/**
+ * \brief Gets the canoical (true) path of a file
+ * \param Path File path (may contain symlinks, relative elements etc.)
+ * \return Absolute path with no symlinks
+ */
extern char *VFS_GetTruePath(char *Path);
+/**
+ * \brief Mounts a filesystem
+ * \param Device Device to mount
+ * \param MountPoint Location to mount
+ * \param Filesystem Filesystem to use
+ * \param Options Options string to pass the driver
+ * \return 1 on succes, -1 on error
+ */
extern int VFS_Mount(char *Device, char *MountPoint, char *Filesystem, char *Options);
+/**
+ * \brief Create a new directory
+ * \param Path Path to new directory (absolute or relative)
+ * \return Boolean success
+ * \note The parent of the directory must exist
+ */
extern int VFS_MkDir(char *Path);
-extern int VFS_Symlink(char *Link, char *Dest);
+/**
+ * \brief Create a symbolic link
+ * \param Name Name of the symbolic link
+ * \param Link File the symlink points to
+ * \return Boolean success (\a Link is not tested for existence)
+ */
+extern int VFS_Symlink(char *Name, char *Link);
+/**
+ * \brief Read from a directory
+ * \param FD File handle returned by ::VFS_Open
+ * \param Dest Destination array for the file name (max 255 bytes)
+ * \return Boolean Success
+ */
extern int VFS_ReadDir(int FD, char *Dest);
#endif
gKernelModules[i].Name,
gKernelModules[i].Version>>8, gKernelModules[i].Version & 0xFF
);
- gKernelModules[i].Init(NULL);
+ if( gKernelModules[i].Init(NULL) == 0 ) {
+ Log("Loading Failed, all modules that depend on this will also fail");
+ baIsLoaded[i] = -1;
+ }
// Mark as loaded
- baIsLoaded[i] = 1;
+ else
+ baIsLoaded[i] = 1;
numToInit --;
}
}
{
char path[VFS_MEMPATH_SIZE];
- VFS_GetMemPath(Buffer, Length, path);
+ VFS_GetMemPath(path, Buffer, Length);
return Module_LoadFile( path, ArgString );
}
extern int Proc_GetMessage(Uint *Err, Uint *Source, void *Buffer);
extern int Proc_Execve(char *File, char **ArgV, char **EnvP);
extern Uint Binary_Load(char *file, Uint *entryPoint);
-extern int VFS_FInfo(int FD, void *Dest, int MaxACLs);
-extern int VFS_GetACL(int FD, void *Dest);
-extern int VFS_ChDir(char *Dest);
extern int Threads_SetName(char *NewName);
extern int Threads_GetPID();
extern int Threads_GetTID();
break;
case SYS_FINFO:
- CHECK_NUM_NONULL( Regs->Arg2, sizeof(struct s_sysFInfo) + Regs->Arg3*sizeof(tVFS_ACL) );
+ CHECK_NUM_NONULL( Regs->Arg2, sizeof(tFInfo) + Regs->Arg3*sizeof(tVFS_ACL) );
// FP, Dest, MaxACLs
ret = VFS_FInfo( Regs->Arg1, (void*)Regs->Arg2, Regs->Arg3 );
break;
}
/**
- * \fn int VFS_Seek(int FD, Sint64 Distance, int Whence)
+ * \fn int VFS_Seek(int FD, Sint64 Offset, int Whence)
* \brief Seek to a new location
* \param FD File descriptor
- * \param Distance Where to go
+ * \param Offset Where to go
* \param Whence From where
*/
-int VFS_Seek(int FD, Sint64 Distance, int Whence)
+int VFS_Seek(int FD, Sint64 Offset, int Whence)
{
tVFS_Handle *h;
// Set relative to current position
if(Whence == 0) {
- h->Position += Distance;
+ h->Position += Offset;
return 0;
}
// Set relative to end of file
if(Whence < 0) {
- h->Position = h->Node->Size - Distance;
+ h->Position = h->Node->Size - Offset;
return 0;
}
// Set relative to start of file
- h->Position = Distance;
+ h->Position = Offset;
return 0;
}
}
/**
- * \fn int VFS_FInfo(int FD, struct s_sysFInfo *Dest, int MaxACLs)
+ * \fn int VFS_FInfo(int FD, tFInfo *Dest, int MaxACLs)
* \brief Retrieve file information
* \return Number of ACLs stored
*/
-int VFS_FInfo(int FD, struct s_sysFInfo *Dest, int MaxACLs)
+int VFS_FInfo(int FD, tFInfo *Dest, int MaxACLs)
{
tVFS_Handle *h;
int max;
// === PROTOTYPES ===
int VFS_Init();
char *VFS_GetTruePath(char *Path);
-void VFS_GetMemPath(void *Base, Uint Length, char *Dest);
+void VFS_GetMemPath(char *Dest, void *Base, Uint Length);
tVFS_Driver *VFS_GetFSByName(char *Name);
int VFS_AddDriver(tVFS_Driver *Info);
void VFS_UpdateDriverFile();
}
/**
- * \fn void VFS_GetMemPath(void *Base, Uint Length, char *Dest)
+ * \fn void VFS_GetMemPath(char *Dest, void *Base, Uint Length)
* \brief Create a VFS memory pointer path
*/
-void VFS_GetMemPath(void *Base, Uint Length, char *Dest)
+void VFS_GetMemPath(char *Dest, void *Base, Uint Length)
{
Log("VFS_GetMemPath: (Base=%p, Length=0x%x, Dest=%p)", Base, Length, Dest);
Dest[0] = '$';
// === CODE ===
/**
- * \fn int VFS_Mount(char *Device, char *MountPoint, char *Filesystem, char *ArgString)
+ * \fn int VFS_Mount(char *Device, char *MountPoint, char *Filesystem, char *Options)
* \brief Mount a device
* \param Device Device string to mount
* \param MountPoint Destination for the mount
* \param Filesystem Filesystem to use for the mount
- * \param ArgString Options to be passed to the filesystem
+ * \param Options Options to be passed to the filesystem
* \return -1 on Invalid FS, -2 on No Mem, 0 on success
*/
-int VFS_Mount(char *Device, char *MountPoint, char *Filesystem, char *ArgString)
+int VFS_Mount(char *Device, char *MountPoint, char *Filesystem, char *Options)
{
tVFS_Mount *mnt;
tVFS_Driver *fs;
int deviceLen = strlen(Device);
int mountLen = strlen(MountPoint);
- int argLen = strlen(ArgString);
+ int argLen = strlen(Options);
// Get the filesystem
fs = VFS_GetFSByName(Filesystem);
memcpy( mnt->MountPoint, MountPoint, mountLen+1 );
mnt->Options = &mnt->StrData[deviceLen+1+mountLen+1];
- memcpy( mnt->Options, ArgString, argLen+1 );
+ memcpy( mnt->Options, Options, argLen+1 );
// Initialise Volume
mnt->RootNode = fs->InitDevice(Device, NULL); //&ArgString);
}
/**
- * \fn int VFS_ChDir(char *New)
* \brief Change current working directory
*/
-int VFS_ChDir(char *New)
+int VFS_ChDir(char *Dest)
{
char *buf;
int fd;
tVFS_Handle *h;
// Create Absolute
- buf = VFS_GetAbsPath(New);
+ buf = VFS_GetAbsPath(Dest);
if(buf == NULL) {
Log("VFS_ChDir: Path expansion failed");
return -1;
DRIVERS = ata_x86
MODULES = FS_Ext2 FDD NE2000 BochsGA
-DISTROOT = /mnt/AcessHDD/Acess2
-ACESSDIR = /home/hodgeja/Projects/Acess2
+#DISTROOT = /mnt/AcessHDD/Acess2
+DISTROOT = ~/Projects/Acess2/Filesystem
+ACESSDIR = ~/Projects/Acess2
ret = 0;\r
break;\r
\r
- case VIDEO_IOCTL_SETMODE:\r
- ret = BGA_int_UpdateMode(*(int*)(Data));\r
- break;\r
- \r
- case VIDEO_IOCTL_GETMODE:\r
- ret = giBGA_CurrentMode;\r
+ case VIDEO_IOCTL_GETSETMODE:\r
+ if( Data )\r
+ ret = BGA_int_UpdateMode(*(int*)(Data));\r
+ else\r
+ ret = giBGA_CurrentMode;\r
break;\r
\r
case VIDEO_IOCTL_FINDMODE:\r
#include <common.h>\r
#include <modules.h>\r
#include <fs_devfs.h>\r
-#include <tpl_drv_common.h>\r
+#include <tpl_drv_disk.h>\r
#include <dma.h>\r
#include <iocache.h>\r
\r
#define FDD_VERSION ((0<<8)|(75))\r
\r
// --- Options\r
-#define USE_CACHE 1 // Use Sector Cache\r
+#define USE_CACHE 0 // Use Sector Cache\r
#define CACHE_SIZE 32 // Number of cachable sectors\r
#define FDD_SEEK_TIMEOUT 10 // Timeout for a seek operation\r
#define MOTOR_ON_DELAY 500 // Miliseconds\r
int track[2];\r
int timer;\r
tVFS_Node Node;\r
+ #if !USE_CACHE\r
+ tIOCache *CacheHandle;\r
+ #endif\r
} t_floppyDevice;\r
\r
/**\r
tVFS_Node *FDD_FindDir(tVFS_Node *dirNode, char *Name);\r
int FDD_IOCtl(tVFS_Node *Node, int ID, void *Data);\r
Uint64 FDD_ReadFS(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer);\r
+// --- 1st Level Disk Access\r
+Uint FDD_ReadSectors(Uint64 SectorAddr, Uint Count, void *Buffer, Uint Disk);\r
// --- Raw Disk Access\r
int FDD_ReadSector(Uint32 disk, Uint64 lba, void *Buffer);\r
int FDD_WriteSector(Uint32 Disk, Uint64 LBA, void *Buffer);\r
// Register with devfs\r
DevFS_AddDevice(&gFDD_DriverInfo);\r
\r
- return 0;\r
+ return 1;\r
}\r
\r
/**\r
* \fn tVFS_Node *FDD_FindDir(tVFS_Node *Node, char *filename);\r
* \brief Find File Routine (for vfs_node)\r
*/\r
-tVFS_Node *FDD_FindDir(tVFS_Node *Node, char *filename)\r
+tVFS_Node *FDD_FindDir(tVFS_Node *Node, char *Filename)\r
{\r
int i;\r
\r
- ENTER("sfilename", filename);\r
+ ENTER("sFilename", Filename);\r
\r
// Sanity check string\r
- if(filename == NULL) {\r
+ if(Filename == NULL) {\r
LEAVE('n');\r
return NULL;\r
}\r
\r
// Check string length (should be 1)\r
- if(filename[0] == '\0' || filename[1] != '\0') {\r
+ if(Filename[0] == '\0' || Filename[1] != '\0') {\r
LEAVE('n');\r
return NULL;\r
}\r
\r
// Get First character\r
- i = filename[0] - '0';\r
+ i = Filename[0] - '0';\r
\r
// Check for 1st disk and if it is present return\r
if(i == 0 && gFDD_Devices[0].type != 0) {\r
return NULL;\r
}\r
\r
+static const char *casIOCTLS[] = {DRV_IOCTLNAMES,DRV_DISK_IOCTLNAMES,NULL};\r
/**\r
- * \fn int FDD_IOCtl(tVFS_Node *node, int id, void *data)\r
+ * \fn int FDD_IOCtl(tVFS_Node *Node, int id, void *data)\r
* \brief Stub ioctl function\r
*/\r
-int FDD_IOCtl(tVFS_Node *node, int id, void *data)\r
+int FDD_IOCtl(tVFS_Node *Node, int ID, void *Data)\r
{\r
- switch(id)\r
+ switch(ID)\r
{\r
- case DRV_IOCTL_TYPE: return DRV_TYPE_DISK;\r
- case DRV_IOCTL_IDENT: memcpy(data, "FDD\0", 4); return 1;\r
- case DRV_IOCTL_VERSION: return FDD_VERSION;\r
- default: return 0;\r
+ case DRV_IOCTL_TYPE:\r
+ return DRV_TYPE_DISK;\r
+ \r
+ case DRV_IOCTL_IDENT:\r
+ if(!CheckMem(Data, 4)) return -1;\r
+ memcpy(Data, "FDD\0", 4);\r
+ return 1;\r
+ \r
+ case DRV_IOCTL_VERSION:\r
+ return FDD_VERSION;\r
+ \r
+ case DRV_IOCTL_LOOKUP:\r
+ if(!CheckString(Data)) return -1;\r
+ return LookupString((char**)casIOCTLS, Data);\r
+ \r
+ case DISK_IOCTL_GETBLOCKSIZE:\r
+ return 512; \r
+ \r
+ default:\r
+ return 0;\r
}\r
}\r
\r
/**\r
- * \fn Uint64 fdd_readFS(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer)\r
+ * \fn Uint64 FDD_ReadFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)\r
* \brief Read Data from a disk\r
*/\r
-Uint64 FDD_ReadFS(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer)\r
+Uint64 FDD_ReadFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)\r
{\r
- int i = 0;\r
- int disk;\r
- Uint32 buf[128];\r
+ int i = 0;\r
+ int disk;\r
+ //Uint32 buf[128];\r
\r
- ENTER("xoff xlen pbuffer", off, len, buffer);\r
+ ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);\r
\r
- if(node == NULL) {\r
+ if(Node == NULL) {\r
LEAVE('i', -1);\r
return -1;\r
}\r
\r
- if(node->Inode != 0 && node->Inode != 1) {\r
+ if(Node->Inode != 0 && Node->Inode != 1) {\r
LEAVE('i', -1);\r
return -1;\r
}\r
\r
- disk = node->Inode;\r
+ disk = Node->Inode;\r
\r
// Update Accessed Time\r
- node->ATime = now();\r
+ Node->ATime = now();\r
\r
- if((off & 0x1FF) || (len & 0x1FF))\r
+ #if 0\r
+ if((Offset & 0x1FF) || (Length & 0x1FF))\r
{\r
// Un-Aligned Offset/Length\r
- int startOff = off>>9;\r
- int sectOff = off&0x1FF;\r
- int sectors = (len+0x1FF)>>9;\r
+ int startOff = Offset >> 9;\r
+ int sectOff = Offset & 0x1FF;\r
+ int sectors = (Length + 0x1FF) >> 9;\r
\r
LOG("Non-aligned Read");\r
\r
//Read Starting Sector\r
if(!FDD_ReadSector(disk, startOff, buf))\r
return 0;\r
- memcpy(buffer, (char*)(buf+sectOff), len>512-sectOff?512-sectOff:len);\r
+ memcpy(Buffer, (char*)(buf+sectOff), Length > 512-sectOff ? 512-sectOff : Length);\r
\r
- //If the data size is one sector or less\r
- if(len <= 512-sectOff) {\r
- LEAVE('X', len);\r
- return len; //Return\r
+ // If the data size is one sector or less\r
+ if(Length <= 512-sectOff)\r
+ {\r
+ LEAVE('X', Length);\r
+ return Length; //Return\r
}\r
- buffer += 512-sectOff;\r
+ Buffer += 512-sectOff;\r
\r
//Read Middle Sectors\r
- for(i=1;i<sectors-1;i++) {\r
+ for( i = 1; i < sectors - 1; i++ )\r
+ {\r
if(!FDD_ReadSector(disk, startOff+i, buf)) {\r
LEAVE('i', -1);\r
return -1;\r
}\r
- memcpy(buffer, buf, 512);\r
- buffer += 512;\r
+ memcpy(Buffer, buf, 512);\r
+ Buffer += 512;\r
}\r
\r
//Read End Sectors\r
if(!FDD_ReadSector(disk, startOff+i, buf))\r
return 0;\r
- memcpy(buffer, buf, (len&0x1FF)-sectOff);\r
+ memcpy(Buffer, buf, (len&0x1FF)-sectOff);\r
- LEAVE('X', len);\r
- return len;\r
+ LEAVE('X', Length);\r
+ return Length;\r
}\r
else\r
{\r
- int count = len >> 9;\r
- int sector = off >> 9;\r
+ int count = Length >> 9;\r
+ int sector = Offset >> 9;\r
LOG("Aligned Read");\r
//Aligned Offset and Length - Simple Code\r
- for(i=0;i<count;i++)\r
+ for( i = 0; i < count; i ++ )\r
{\r
FDD_ReadSector(disk, sector, buf);\r
memcpy(buffer, buf, 512);\r
buffer += 512;\r
sector++;\r
}
- LEAVE('i', len);\r
- return len;\r
+ LEAVE('i', Length);\r
+ return Length;\r
}\r
+ #endif\r
+ \r
+ i = DrvUtil_ReadBlock(Offset, Length, Buffer, FDD_ReadSectors, 512, disk);\r
+ LEAVE('i', i);\r
+ return i;\r
+}\r
+\r
+/**\r
+ * \fn Uint FDD_ReadSectors(Uint64 SectorAddr, Uint Count, void *Buffer, Uint32 Disk)\r
+ * \brief Reads \a Count contiguous sectors from a disk\r
+ * \param SectorAddr Address of the first sector\r
+ * \param Count Number of sectors to read\r
+ * \param Buffer Destination Buffer\r
+ * \param Disk Disk Number\r
+ * \return Number of sectors read\r
+ * \note Used as a ::DrvUtil_ReadBlock helper\r
+ */\r
+Uint FDD_ReadSectors(Uint64 SectorAddr, Uint Count, void *Buffer, Uint Disk)\r
+{\r
+ Uint ret = 0;\r
+ while(Count --)\r
+ {\r
+ if( FDD_ReadSector(Disk, SectorAddr, Buffer) != 1 )\r
+ return ret;\r
+ \r
+ Buffer = (void*)( (tVAddr)Buffer + 512 );\r
+ SectorAddr ++;\r
+ ret ++;\r
+ }\r
+ return ret;\r
}\r
\r
/**\r
LOG("Read %i from Disk", lba);\r
FDD_FreeCacheSpinlock();\r
#else\r
- if( IOCache_Read( gFDD_Devices[Disk].Cache, SectorAddr, Buffer ) == 1 ) {\r
+ if( IOCache_Read( gFDD_Devices[Disk].CacheHandle, SectorAddr, Buffer ) == 1 ) {\r
LEAVE('i', 1);\r
return 1;\r
}\r
base = cPORTBASE[Disk>>1];\r
\r
LOG("Calculating Disk Dimensions");\r
- //Get CHS position\r
+ // Get CHS position\r
if(FDD_int_GetDims(gFDD_Devices[Disk].type, lba, &cyl, &head, &sec, &spt) != 1) {\r
LEAVE('i', -1);\r
return -1;\r
return 1;\r
}\r
\r
+/**\r
+ * \fn int FDD_WriteSector(Uint32 Disk, Uint64 LBA, void *Buffer)\r
+ * \brief Write a sector to the floppy disk\r
+ * \note Not Implemented\r
+ */\r
+int FDD_WriteSector(Uint32 Disk, Uint64 LBA, void *Buffer)\r
+{\r
+ Warning("[FDD ] Read Only at the moment");\r
+ return -1;\r
+}\r
+\r
/**\r
* \fn int FDD_int_SeekTrack(int disk, int track)\r
* \brief Seek disk to selected track\r
gNe2k_DriverInfo.RootNode.Size = giNe2k_CardCount;
DevFS_AddDevice( &gNe2k_DriverInfo );
- return 0;
+ return 1;
}
/**