Merge branch 'master' of git://git.ucc.asn.au/acess2
authorJohn Hodge <[email protected]>
Tue, 13 Apr 2010 01:35:29 +0000 (09:35 +0800)
committerJohn Hodge <[email protected]>
Tue, 13 Apr 2010 01:35:29 +0000 (09:35 +0800)
161 files changed:
.gitignore
Kernel/Doxyfile.api
Kernel/Makefile
Kernel/Makefile.BuildNum
Kernel/arch/x86/Makefile
Kernel/arch/x86/desctab.asm
Kernel/arch/x86/errors.c
Kernel/arch/x86/include/arch.h
Kernel/arch/x86/include/desctab.h [new file with mode: 0644]
Kernel/arch/x86/include/multiboot2.h [new file with mode: 0644]
Kernel/arch/x86/include/vm8086.h [new file with mode: 0644]
Kernel/arch/x86/irq.c
Kernel/arch/x86/link.ld
Kernel/arch/x86/main.c
Kernel/arch/x86/mm_phys.c
Kernel/arch/x86/mm_virt.c
Kernel/arch/x86/proc.c
Kernel/arch/x86/start.asm
Kernel/arch/x86/vm8086.c [new file with mode: 0644]
Kernel/bin/elf.c
Kernel/bin/elf.h
Kernel/bin/pe.c
Kernel/binary.c
Kernel/debug.c
Kernel/drv/dma.c
Kernel/drv/fifo.c
Kernel/drv/kb.c
Kernel/drv/pci.c
Kernel/drv/proc.c
Kernel/drv/vga.c
Kernel/drv/vterm.c
Kernel/heap.c
Kernel/include/acess.h
Kernel/include/apidoc/arch_x86.h [new file with mode: 0644]
Kernel/include/apidoc_mainpage.h
Kernel/include/dma.h
Kernel/include/drv_pci.h
Kernel/include/errno.h
Kernel/include/fs_devfs.h
Kernel/include/mboot.h
Kernel/include/modules.h
Kernel/include/threads.h
Kernel/include/tpl_drv_video.h
Kernel/include/vfs.h
Kernel/include/vfs_ext.h
Kernel/lib.c
Kernel/logging.c [new file with mode: 0644]
Kernel/modules.c
Kernel/syscalls.c
Kernel/system.c
Kernel/threads.c
Kernel/vfs/fs/devfs.c
Kernel/vfs/fs/fat.c [deleted file]
Kernel/vfs/fs/fs_fat.h [deleted file]
Kernel/vfs/main.c
Kernel/vfs/memfile.c
Kernel/vfs/mount.c
Kernel/vfs/nodecache.c
Makefile
Makefile.cfg
Modules/Display/BochsGA/bochsvbe.c
Modules/Display/Makefile.tpl
Modules/Display/VESA/Makefile [new file with mode: 0644]
Modules/Display/VESA/common.h [new file with mode: 0644]
Modules/Display/VESA/main.c [new file with mode: 0644]
Modules/Filesystems/Ext2/Makefile [new file with mode: 0644]
Modules/Filesystems/Ext2/dir.c [new file with mode: 0644]
Modules/Filesystems/Ext2/ext2.c [new file with mode: 0644]
Modules/Filesystems/Ext2/ext2_common.h [new file with mode: 0644]
Modules/Filesystems/Ext2/ext2fs.h [new file with mode: 0644]
Modules/Filesystems/Ext2/read.c [new file with mode: 0644]
Modules/Filesystems/Ext2/write.c [new file with mode: 0644]
Modules/Filesystems/FAT/Makefile [new file with mode: 0644]
Modules/Filesystems/FAT/fat.c [new file with mode: 0644]
Modules/Filesystems/FAT/fs_fat.h [new file with mode: 0644]
Modules/Filesystems/FS_Ext2/Makefile [deleted file]
Modules/Filesystems/FS_Ext2/dir.c [deleted file]
Modules/Filesystems/FS_Ext2/ext2.c [deleted file]
Modules/Filesystems/FS_Ext2/ext2_common.h [deleted file]
Modules/Filesystems/FS_Ext2/ext2fs.h [deleted file]
Modules/Filesystems/FS_Ext2/read.c [deleted file]
Modules/Filesystems/FS_Ext2/write.c [deleted file]
Modules/Filesystems/FS_NFS/Makefile [deleted file]
Modules/Filesystems/FS_NFS/common.h [deleted file]
Modules/Filesystems/FS_NFS/main.c [deleted file]
Modules/Filesystems/InitRD/.gitignore [new file with mode: 0644]
Modules/Filesystems/InitRD/GenerateInitRD.php [new file with mode: 0644]
Modules/Filesystems/InitRD/Makefile [new file with mode: 0644]
Modules/Filesystems/InitRD/files.lst [new file with mode: 0644]
Modules/Filesystems/InitRD/initrd.h [new file with mode: 0644]
Modules/Filesystems/InitRD/main.c [new file with mode: 0644]
Modules/Filesystems/Makefile.tpl
Modules/Filesystems/NFS/Makefile [new file with mode: 0644]
Modules/Filesystems/NFS/common.h [new file with mode: 0644]
Modules/Filesystems/NFS/main.c [new file with mode: 0644]
Modules/IPStack/arp.c
Modules/IPStack/icmp.c
Modules/IPStack/ipstack.h
Modules/IPStack/ipv4.c
Modules/IPStack/link.c
Modules/IPStack/main.c
Modules/IPStack/tcp.c
Modules/Interfaces/EDI/Makefile [new file with mode: 0644]
Modules/Interfaces/EDI/edi/acess-edi.h [new file with mode: 0644]
Modules/Interfaces/EDI/edi/edi.h [new file with mode: 0644]
Modules/Interfaces/EDI/edi/edi_devices.h [new file with mode: 0644]
Modules/Interfaces/EDI/edi/edi_dma_streams.h [new file with mode: 0644]
Modules/Interfaces/EDI/edi/edi_interrupts.h [new file with mode: 0644]
Modules/Interfaces/EDI/edi/edi_memory_mapping.h [new file with mode: 0644]
Modules/Interfaces/EDI/edi/edi_objects.h [new file with mode: 0644]
Modules/Interfaces/EDI/edi/edi_port_io.h [new file with mode: 0644]
Modules/Interfaces/EDI/edi/edi_pthreads.h [new file with mode: 0644]
Modules/Interfaces/EDI/edi/helpers.h [new file with mode: 0644]
Modules/Interfaces/EDI/edi_int.inc.c [new file with mode: 0644]
Modules/Interfaces/EDI/edi_io.inc.c [new file with mode: 0644]
Modules/Interfaces/EDI/main.c [new file with mode: 0644]
Modules/Interfaces/UDI/cb.c
Modules/Interfaces/UDI/main.c
Modules/Interfaces/UDI/strmem.c
Modules/Makefile.tpl
Modules/Network/Makefile.tpl
Modules/Network/NE2000/ne2000.c
Modules/Network/RTL8139/main.c [new file with mode: 0644]
Modules/Storage/ATA/main.c
Modules/Storage/FDD/fdd.c
Modules/Storage/Makefile.tpl
Modules/USB/Core/Makefile [new file with mode: 0644]
Modules/USB/Core/main.c [new file with mode: 0644]
Modules/USB/Core/uhci.c [new file with mode: 0644]
Modules/USB/Core/uhci.h [new file with mode: 0644]
Modules/USB/Core/usb.c [new file with mode: 0644]
Modules/USB/Core/usb.h [new file with mode: 0644]
Modules/USB/Makefile [deleted file]
Modules/USB/Makefile.tpl [new file with mode: 0644]
Modules/USB/main.c [deleted file]
Modules/USB/uhci.c [deleted file]
Modules/USB/uhci.h [deleted file]
Modules/USB/usb.c [deleted file]
Modules/USB/usb.h [deleted file]
Usermode/Applications/CLIShell_src/Makefile
Usermode/Applications/CLIShell_src/main.c
Usermode/Applications/axwin2_src/Shell_src/Makefile [new file with mode: 0644]
Usermode/Applications/axwin2_src/Shell_src/main.c [new file with mode: 0644]
Usermode/Applications/axwin2_src/WM/common.h
Usermode/Applications/axwin2_src/WM/wm.h [new file with mode: 0644]
Usermode/Applications/ifconfig_src/main.c
Usermode/Applications/mount_src/main.c
Usermode/Filesystem/Conf/BootConf.cfg
Usermode/Libraries/Makefile.tpl [new file with mode: 0644]
Usermode/Libraries/crt0.o_src/Makefile
Usermode/Libraries/ld-acess.so_src/loadlib.c
Usermode/Libraries/libaxwin2.so_src/Makefile [new file with mode: 0644]
Usermode/Libraries/libaxwin2.so_src/common.h [new file with mode: 0644]
Usermode/Libraries/libaxwin2.so_src/main.c [new file with mode: 0644]
Usermode/Libraries/libaxwin2.so_src/messages.c [new file with mode: 0644]
Usermode/Libraries/libaxwin2.so_src/windows.c [new file with mode: 0644]
Usermode/Libraries/libreadline.so_src/Makefile [new file with mode: 0644]
Usermode/Libraries/libreadline.so_src/main.c
Usermode/include/axwin/axwin.h [new file with mode: 0644]
Usermode/include/axwin/messages.h
Usermode/include/readline.h [new file with mode: 0644]

index a37ca30..b979781 100644 (file)
@@ -6,10 +6,10 @@
 *.ao
 *.ao.*
 *.so
+*.so.*
 *.i486
 *.i386
 *.bin
 *.dsm
 *.dmp
-Map.txt
-map.txt
+*.txt
index 7957e58..d445416 100644 (file)
@@ -568,9 +568,13 @@ WARN_LOGFILE           =
 
 INPUT                  = include/apidoc_mainpage.h \
                          include/binary.h \
+                         include/modules.h \
                          include/vfs.h include/vfs_ext.h \
                                                 include/fs_devfs.h \
-                         include/iocache.h include/
+                         include/iocache.h \
+                         include/apidoc/arch_x86.h \
+                         include/tpl_drv_common.h \
+                         include/tpl_drv_video.h
 
 # 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 
index 8593d6f..5e6fafb 100644 (file)
@@ -26,12 +26,12 @@ ifeq ($(DEBUG_BUILD),yes)
 endif
 
 OBJ = $(addprefix arch/$(ARCHDIR)/,$(A_OBJ))
-OBJ += heap.o messages.o debug.o modules.o lib.o syscalls.o system.o threads.o drvutil.o
+OBJ += heap.o messages.o debug.o modules.o lib.o syscalls.o system.o threads.o drvutil.o logging.o
+OBJ += $(addprefix vfs/fs/, $(addsuffix .o,$(FILESYSTEMS)))
+OBJ += drv/vterm.o drv/proc.o drv/fifo.o drv/iocache.o drv/dma.o drv/pci.o drv/kb.o drv/vga.o
 OBJ += binary.o bin/elf.o bin/pe.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/proc.o 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)))
index 55c6592..dc8d809 100644 (file)
@@ -1 +1 @@
-BUILD_NUM = 1513
+BUILD_NUM = 1822
index 87dd2b2..708c8dc 100644 (file)
@@ -31,5 +31,5 @@ endif
 
 A_OBJ  = start.ao main.o lib.o desctab.ao errors.o irq.o
 A_OBJ += mm_phys.o mm_virt.o
-A_OBJ += proc.o time.o
+A_OBJ += proc.o time.o vm8086.o
 #A_OBJ += gdb_stub.o
index 737570b..43bd8e4 100644 (file)
@@ -29,6 +29,7 @@ gGDTPtr:
        dd      gGDT
 ; IDT
 ALIGN 8
+[global gIDT]
 gIDT:
        times   256     dd      0x00080000,0x00000F00
 [global gIDTPtr]
@@ -146,7 +147,6 @@ Isr%1:
 %macro DEF_IRQ 1
 [global Isr%1]
 Isr%1:
-       ;cli    ; HACK!
        push    0
        push    %1
        jmp     IRQCommon
@@ -212,6 +212,12 @@ ErrorCommon:
        push fs
        push gs
        
+       mov ax, 0x10
+       mov ds, ax
+       mov es, ax
+       mov fs, ax
+       mov gs, ax
+       
        push esp
        call ErrorHandler
        add esp, 4
@@ -258,6 +264,12 @@ IRQCommon:
        push fs
        push gs
        
+       mov ax, 0x10
+       mov ds, ax
+       mov es, ax
+       mov fs, ax
+       mov gs, ax
+       
        push esp
        call IRQ_Handler
        add esp, 4
@@ -281,6 +293,12 @@ SchedulerBase:
        push fs
        push gs
        
+       mov ax, 0x10
+       mov ds, ax
+       mov es, ax
+       mov fs, ax
+       mov gs, ax
+       
        mov eax, [esp+12*4]     ; CPU Number
        push eax        ; Pus as argument
        
index cfc7075..31c385f 100644 (file)
@@ -11,6 +11,7 @@
 
 // === IMPORTS ===
 extern void    MM_PageFault(Uint Addr, Uint ErrorCode, tRegs *Regs);
+extern void    VM8086_GPF(tRegs *Regs);
 extern void Threads_Dump();
 
 // === PROTOTYPES ===
@@ -42,8 +43,15 @@ void __stack_chk_fail()
 void ErrorHandler(tRegs *Regs)
 {
        Uint    cr;
+       
+       //if( Regs && !(Regs->int_num == 13 && Regs->eflags & 0x20000) )
+       //      __asm__ __volatile__ ("xchg %bx, %bx");
+       //Log_Debug("X86", "Regs = %p", Regs);
+       //Log_Debug("X86", "Error %i at 0x%08x", Regs->int_num, Regs->eip);
+       
        __asm__ __volatile__ ("cli");
        
+       // Page Fault
        if(Regs->int_num == 14)
        {
                __asm__ __volatile__ ("mov %%cr2, %0":"=r"(cr));
@@ -51,10 +59,20 @@ void ErrorHandler(tRegs *Regs)
                return ;
        }
        
+       // VM8086 GPF
+       if(Regs->int_num == 13 && Regs->eflags & 0x20000)
+       {
+               VM8086_GPF(Regs);
+               return ;
+       }
+       
        Warning("CPU Error %i - %s, Code: 0x%x",
                Regs->int_num, csaERROR_NAMES[Regs->int_num], Regs->err_code);
        Warning(" CS:EIP = 0x%04x:%08x", Regs->cs, Regs->eip);
-       Warning(" SS:ESP = 0x%04x:%08x", Regs->ss, Regs->esp);
+       if(Regs->cs == 0x08)
+               Warning(" SS:ESP = 0x0010:%08x", 0x10, (Uint)Regs+sizeof(tRegs));
+       else
+               Warning(" SS:ESP = 0x%04x:%08x", Regs->ss, Regs->esp);
        Warning(" EFLAGS = 0x%08x", Regs->eflags);
        Warning(" EAX %08x ECX %08x EDX %08x EBX %08x",
                Regs->eax, Regs->ecx, Regs->edx, Regs->ebx);
@@ -73,7 +91,7 @@ void ErrorHandler(tRegs *Regs)
        
        switch( Regs->int_num )
        {
-       case 6:
+       case 6: // #UD
                Warning(" Offending bytes: %02x %02x %02x %02x",
                        *(Uint8*)Regs->eip+0, *(Uint8*)Regs->eip+1,
                        *(Uint8*)Regs->eip+2, *(Uint8*)Regs->eip+3);
index 1826757..4007a71 100644 (file)
@@ -44,6 +44,7 @@
 
 // === MACROS ===
 typedef volatile int   tSpinlock;
+#define IS_LOCKED(lockptr)     (!!(*(tSpinlock*)lockptr))
 #define LOCK(lockptr)  do {int v=1;\
        while(v)__asm__ __volatile__("lock xchgl %%eax, (%%edi)":"=a"(v):"a"(1),"D"(lockptr));}while(0)
 #define        RELEASE(lockptr)        __asm__ __volatile__("lock andl $0, (%%edi)"::"D"(lockptr));
@@ -97,18 +98,6 @@ typedef struct {
        Uint    Resvd4[1];      // SS
 } tSyscallRegs;
 
-typedef struct {
-       Uint16  LimitLow;
-       Uint16  BaseLow;
-       Uint8   BaseMid;
-       Uint8   Access;
-       struct {
-               unsigned LimitHi:       4;
-               unsigned Flags:         4;
-       } __attribute__ ((packed));
-       Uint8   BaseHi;
-} __attribute__ ((packed)) tGDT;
-
 typedef struct {
        #if USE_PAE
        Uint    PDPT[4];
diff --git a/Kernel/arch/x86/include/desctab.h b/Kernel/arch/x86/include/desctab.h
new file mode 100644 (file)
index 0000000..47a462a
--- /dev/null
@@ -0,0 +1,25 @@
+/**
+ */
+#ifndef _DESCTAB_H_
+#define _DESCTAB_H_
+
+typedef struct {
+       Uint16  LimitLow;
+       Uint16  BaseLow;
+       Uint8   BaseMid;
+       Uint8   Access;
+       struct {
+               unsigned LimitHi:       4;
+               unsigned Flags:         4;
+       } __attribute__ ((packed));
+       Uint8   BaseHi;
+} __attribute__ ((packed)) tGDT;
+
+typedef struct {
+       Uint16  OffsetLo;
+       Uint16  CS;
+       Uint16  Flags;
+       Uint16  OffsetHi;
+} __attribute__ ((packed)) tIDT;
+
+#endif
diff --git a/Kernel/arch/x86/include/multiboot2.h b/Kernel/arch/x86/include/multiboot2.h
new file mode 100644 (file)
index 0000000..735109a
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Acess 2
+ * By John Hodge (thePowersGang)
+ *
+ * multiboot2.h
+ * - Multiboot 2 Header
+ */
+#ifndef _MULTIBOOT2_H_
+#define _MULTIBOOT2_H_
+
+#define MULTIBOOT2_MAGIC       0x36D76289
+
+typedef struct sMultiboot2Info
+{
+       Uint32  TotalSize;
+       Uint32  Reserved;       // SBZ
+}      tMultiboot2Info;
+
+#endif
diff --git a/Kernel/arch/x86/include/vm8086.h b/Kernel/arch/x86/include/vm8086.h
new file mode 100644 (file)
index 0000000..353ad7a
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Acess2 VM8086 BIOS Interface
+ * - By John Hodge (thePowersGang)
+ *
+ * vm8086.h
+ * - Core Header
+ */
+#ifndef _VM80806_H_
+#define _VM80806_H_
+
+// === TYPES ===
+/**
+ * \note Semi-opaque - Past \a .IP, the implementation may add any data
+ *       it needs to the state.
+ */
+typedef struct sVM8086
+{
+       Uint16  AX, CX, DX, BX;
+       Uint16  BP, SP, SI, DI;
+       
+       Uint16  SS, DS, ES;
+       
+       Uint16  CS, IP;
+       
+       struct sVM8086_InternalData     *Internal;
+}      tVM8086;
+
+// === FUNCTIONS ===
+/**
+ * \brief Create an instance of the VM8086 Emulator
+ * \note Do not free this pointer with ::free, instead use ::VM8086_Free
+ * \return Pointer to a tVM8086 structure, this structure may be larger than
+ *         tVM8086 due to internal data.
+ */
+extern tVM8086 *VM8086_Init(void);
+/**
+ * \brief Free an allocated tVM8086 structure
+ * \param State        Emulator state to free
+ */
+extern void    VM8086_Free(tVM8086 *State);
+/**
+ * \brief Allocate a piece of memory in the emulated address space and
+ *        return a host and emulated pointer to it.
+ * \param State        Emulator state
+ * \param Size Size of memory block
+ * \param Segment      Pointer to location to store the allocated memory's segment
+ * \param Offset       Pointet to location to store the allocated memory's offset
+ * \return Host pointer to the allocated memory
+ */
+extern void    *VM8086_Allocate(tVM8086 *State, int Size, Uint16 *Segment, Uint16 *Offset);
+/**
+ * \brief Gets a pointer to a piece of emulated memory
+ * \todo Only 1 machine page is garenteed to be contiguous
+ * \param State        Emulator State
+ * \param Segment      Source Segment
+ * \param Offset       Source Offset
+ * \return Host pointer to the emulated memory
+ */
+extern void *VM8086_GetPointer(tVM8086 *State, Uint16 Segment, Uint16 Ofs);
+/**
+ * \brief Calls a real-mode interrupt described by the current state of the IVT.
+ * \param State        Emulator State
+ * \param Interrupt    BIOS Interrupt to call
+ */
+extern void    VM8086_Int(tVM8086 *State, Uint8 Interrupt);
+
+#endif
index 9e0647f..7ff1fe9 100644 (file)
@@ -49,12 +49,12 @@ int IRQ_AddHandler( int Num, void (*Callback)(int) )
        for( i = 0; i < MAX_CALLBACKS_PER_IRQ; i++ )
        {
                if( gIRQ_Handlers[Num][i] == NULL ) {
-                       Log("IRQ_AddHandler: Added IRQ%i Cb#%i %p", Num, i, Callback);
+                       Log_Log("IRQ", "Added IRQ%i Cb#%i %p", Num, i, Callback);
                        gIRQ_Handlers[Num][i] = Callback;
                        return 1;
                }
        }
 
-       Warning("IRQ_AddHandler - No free callbacks on IRQ%i", Num);
+       Log_Warning("IRQ", "No free callbacks on IRQ%i", Num);
        return 0;
 }
index a142747..2fe1764 100644 (file)
@@ -3,12 +3,13 @@
  * Linker Script
  */
 
-lowStart = start - 0xC0000000;
-ENTRY(lowStart)
+//lowStart = start - 0xC0000000;
+ENTRY(start)
 OUTPUT_FORMAT(elf32-i386)
 
 SECTIONS {
        . = 0x100000;
+       __load_addr = .;
        .multiboot : AT(ADDR(.multiboot)) {
                *(.multiboot)
        }
@@ -58,6 +59,7 @@ SECTIONS {
                *(.data)
        }
 
+       __bss_start = .;
        .bss : AT(ADDR(.bss) - 0xC0000000) {
                _sbss = .;
                *(COMMON)
index f6879f8..fa3cb45 100644 (file)
@@ -5,6 +5,7 @@
  */
 #include <acess.h>
 #include <mboot.h>
+#include <multiboot2.h>
 #include <init.h>
 #include <mm_virt.h>
 #include <mp.h>
 #define        VGA_ERRORS      0
 
 // === IMPORTS ===
-extern void    Heap_Install();
-extern void    Desctab_Install();
-extern void    MM_PreinitVirtual();
+extern void    Heap_Install(void);
+extern void    Desctab_Install(void);
+extern void    MM_PreinitVirtual(void);
 extern void    MM_Install(tMBoot_Info *MBoot);
-extern void MM_InstallVirtual();
-extern void    Threads_Init();
-extern int     Time_Setup();
+extern void MM_InstallVirtual(void);
+extern void    Threads_Init(void);
+extern int     Time_Setup(void);
 extern Uint    Proc_Clone(Uint *Err, Uint Flags);
-extern void    Threads_Sleep();
-extern void    Threads_Exit();
+extern void    Threads_Sleep(void);
+extern void    Threads_Exit(void);
+
+extern int     Modules_LoadBuiltins(void);
 
 // === GLOBALS ===
+char   *gsBootCmdLine = NULL;
 
 // === CODE ===
-int kmain(Uint MbMagic, tMBoot_Info *MbInfo)
+int kmain(Uint MbMagic, void *MbInfoPtr)
 {
         int    i;
        tMBoot_Module   *mods;
+       tMBoot_Info     *mbInfo;
        
-       // Adjust Multiboot structure address
-       MbInfo = (void*)( (Uint)MbInfo + KERNEL_BASE );
+       Log("MbMagic = %08x", MbMagic);
+       Log("MbInfoPtr = %p", MbInfoPtr);
        
+       // Set up non-boot info dependent stuff
        Desctab_Install();      // Set up GDT and IDT
        MM_PreinitVirtual();    // Initialise vital mappings
-       MM_Install( MbInfo );   // Set up physical memory manager
+       
+       switch(MbMagic)
+       {
+       // Multiboot 1
+       case MULTIBOOT_MAGIC:
+               // Adjust Multiboot structure address
+               mbInfo = (void*)( (Uint)MbInfoPtr + KERNEL_BASE );
+               gsBootCmdLine = (char*)(mbInfo->CommandLine + KERNEL_BASE);
+               
+               MM_Install( mbInfo );   // Set up physical memory manager
+               break;
+       
+       // Multiboot 2
+       case MULTIBOOT2_MAGIC:
+               Warning("Multiboot 2 Not yet supported");
+               //MM_InstallMBoot2( MbInfo );   // Set up physical memory manager
+               return 0;
+               break;
+       
+       default:
+               Panic("Multiboot magic invalid %08x, expected %08x or %08x\n",
+                       MbMagic, MULTIBOOT_MAGIC, MULTIBOOT2_MAGIC);
+               return 0;
+       }
+       
        MM_InstallVirtual();    // Clean up virtual address space
        Heap_Install();         // Create initial heap
        
-       Log("Starting Multitasking...");
+       //Log_Log("Arch", "Starting Multitasking...");
        // Start Multitasking
        Threads_Init();
        
        // Start Timers
        Time_Setup();
        
-       Log("Starting VFS...");
+       Log_Log("Arch", "Starting VFS...");
        // Load Virtual Filesystem
        VFS_Init();
        
-       Log("Loading Modules...");
+       // Initialise builtin modules
+       Log_Log("Arch", "Initialising builtin modules...");
+       Modules_LoadBuiltins();
+       
+       Log_Log("Arch", "Loading %i Modules...", mbInfo->ModuleCount);
        
        // Load initial modules
-       mods = (void*)( MbInfo->Modules + KERNEL_BASE );
-       for(i=0;i<MbInfo->ModuleCount;i++)
+       mods = (void*)( mbInfo->Modules + KERNEL_BASE );
+       for( i = 0; i < mbInfo->ModuleCount; i ++ )
        {
                // Adjust into higher half
                mods[i].Start += KERNEL_BASE;
                mods[i].End += KERNEL_BASE;
                mods[i].String += KERNEL_BASE;
                
-               Log("Loading '%s'", mods[i].String);
+               Log_Log("Arch", "Loading '%s'", mods[i].String);
                
                if( !Module_LoadMem( (void *)mods[i].Start, mods[i].End-mods[i].Start, (char *)mods[i].String ) )
                {
-                       Warning("Unable to load module\n");
+                       Log_Warning("Arch", "Unable to load module\n");
                }
        }
        
        // Pass on to Independent Loader
-       Log("Loading Configuration...");
-       System_Init( (char*)(MbInfo->CommandLine + KERNEL_BASE) );
+       Log_Log("Arch", "Starting system");
+       System_Init( gsBootCmdLine );
        
        // Sleep forever (sleeping beauty)
-       for(;;) Threads_Sleep();
+       for(;;)
+               Threads_Sleep();
        return 0;
 }
index e4199e3..f091c63 100644 (file)
@@ -39,10 +39,12 @@ void MM_Install(tMBoot_Info *MBoot)
        tMBoot_MMapEnt  *ent;
        
        // --- Find largest address
+       Log("MBoot->MMapAddr = %08x", MBoot->MMapAddr);
        MBoot->MMapAddr |= KERNEL_BASE;
        ent = (void *)( MBoot->MMapAddr );
        while( (Uint)ent < MBoot->MMapAddr + MBoot->MMapLength )
        {
+               Log(" ent->Size = %08x", ent->Size);
                // Adjust for size
                ent->Size += 4;
                
@@ -71,7 +73,7 @@ void MM_Install(tMBoot_Info *MBoot)
                ent = (tMBoot_MMapEnt *)( (Uint)ent + ent->Size );
        }
        
-       // Get used page count
+       // Get used page count (Kernel)
        kernelPages = (Uint)&gKernelEnd - KERNEL_BASE - 0x100000;
        kernelPages += 0xFFF;   // Page Align
        kernelPages >>= 12;
@@ -89,10 +91,12 @@ void MM_Install(tMBoot_Info *MBoot)
        // Mark Multiboot's pages as taken
        // - Structure
        MM_RefPhys( (Uint)MBoot - KERNEL_BASE );
+       Log("MBoot->ModuleCount = %i", MBoot->ModuleCount);
        // - Module List
        for(i = (MBoot->ModuleCount*sizeof(tMBoot_Module)+0xFFF)>12; i--; )
                MM_RefPhys( MBoot->Modules + (i << 12) );
        // - Modules
+       Log("MBoot->Modules = %p", MBoot->Modules);
        mods = (void*)(MBoot->Modules + KERNEL_BASE);
        for(i = 0; i < MBoot->ModuleCount; i++)
        {
@@ -207,8 +211,13 @@ tPAddr MM_AllocPhysRange(int Pages, int MaxBits)
         int    i, idx, sidx;
        tPAddr  ret;
        
+       ENTER("iPages iMaxBits", Pages, MaxBits);
+       
        // Sanity Checks
-       if(MaxBits < 0) return 0;
+       if(MaxBits < 0) {
+               LEAVE('i', 0);
+               return 0;
+       }
        if(MaxBits > PHYS_BITS) MaxBits = PHYS_BITS;
        
        // Lock
@@ -226,16 +235,28 @@ tPAddr MM_AllocPhysRange(int Pages, int MaxBits)
        b = idx % 32;
        a = idx / 32;
        
+       #if 0
+       LOG("a=%i, b=%i, idx=%i, sidx=%i", a, b, idx, sidx);
+       
        // Find free page
-       for( ; gaSuperBitmap[a] == -1 && a --; );
+       for( ; gaSuperBitmap[a] == -1 && a --; )        b = 31;
        if(a < 0) {
                RELEASE( &giPhysAlloc );
                Warning("MM_AllocPhysRange - OUT OF MEMORY (Called by %p)", __builtin_return_address(0));
+               LEAVE('i', 0);
                return 0;
        }
-       for( ; gaSuperBitmap[a] & (1 << b); b-- );
+       LOG("a = %i", a);
+       for( ; gaSuperBitmap[a] & (1 << b); b-- )       sidx = 31;
+       LOG("b = %i", b);
        idx = a * 32 + b;
-       for( ; gaPageBitmap[idx] & (1 << sidx); sidx-- );
+       for( ; gaPageBitmap[idx] & (1 << sidx); sidx-- )
+               LOG("gaPageBitmap[%i] = 0x%08x", idx, gaPageBitmap[idx]);
+       
+       LOG("idx = %i, sidx = %i", idx, sidx);
+       #else
+       
+       #endif
        
        // Check if the gap is large enough
        while( idx >= 0 )
@@ -280,6 +301,8 @@ tPAddr MM_AllocPhysRange(int Pages, int MaxBits)
        if( idx < 0 ) {
                RELEASE( &giPhysAlloc );
                Warning("MM_AllocPhysRange - OUT OF MEMORY (Called by %p)", __builtin_return_address(0));
+               LEAVE('i', 0);
+               return 0;
        }
        
        // Mark pages used
@@ -289,7 +312,7 @@ tPAddr MM_AllocPhysRange(int Pages, int MaxBits)
                        gaPageReferences[idx*32+sidx] = 1;
                gaPageBitmap[ idx ] |= 1 << sidx;
                sidx ++;
-               if(sidx == 32) {        sidx = 0;       idx ++; }
+               if(sidx == 32) { sidx = 0;      idx ++; }
        }
        
        // Get address
@@ -301,6 +324,7 @@ tPAddr MM_AllocPhysRange(int Pages, int MaxBits)
        // Release Spinlock
        RELEASE( &giPhysAlloc );
        
+       LEAVE('X', ret);
        return ret;
 }
 
index 958b9f1..cf77b87 100644 (file)
@@ -9,7 +9,7 @@
  * 0xFE - Unused
  * 0xFF - System Calls / Kernel's User Code
  */
-#define DEBUG  1
+#define DEBUG  0
 #define SANITY 1
 #include <acess.h>
 #include <mm_phys.h>
@@ -208,7 +208,7 @@ void MM_PageFault(tVAddr Addr, Uint ErrorCode, tRegs *Regs)
                        (ErrorCode&1?"bad/locked":"non-present"),
                        (ErrorCode&16?" (Instruction Fetch)":"")
                        );
-               Warning("User Pagefault: Instruction at %p accessed %p", Regs->eip, Addr);
+               Warning("User Pagefault: Instruction at %04x:%08x accessed %p", Regs->cs, Regs->eip, Addr);
                __asm__ __volatile__ ("sti");   // Restart IRQs
                Threads_SegFault(Addr);
                return ;
@@ -895,10 +895,10 @@ void MM_FreeTemp(tVAddr VAddr)
 }
 
 /**
- * \fn tVAddr MM_MapHWPage(tPAddr PAddr, Uint Number)
+ * \fn tVAddr MM_MapHWPages(tPAddr PAddr, Uint Number)
  * \brief Allocates a contigous number of pages
  */
-tVAddr MM_MapHWPage(tPAddr PAddr, Uint Number)
+tVAddr MM_MapHWPages(tPAddr PAddr, Uint Number)
 {
         int    i, j;
        
@@ -962,7 +962,7 @@ tVAddr MM_AllocDMA(int Pages, int MaxBits, tPAddr *PhysAddr)
        {
                phys = MM_AllocPhys();
                *PhysAddr = phys;
-               ret = MM_MapHWPage(phys, 1);
+               ret = MM_MapHWPages(phys, 1);
                if(ret == 0) {
                        MM_DerefPhys(phys);
                        LEAVE('i', 0);
@@ -981,7 +981,7 @@ tVAddr MM_AllocDMA(int Pages, int MaxBits, tPAddr *PhysAddr)
        }
        
        // Allocated successfully, now map
-       ret = MM_MapHWPage(phys, Pages);
+       ret = MM_MapHWPages(phys, Pages);
        if( ret == 0 ) {
                // If it didn't map, free then return 0
                for(;Pages--;phys+=0x1000)
@@ -996,10 +996,10 @@ tVAddr MM_AllocDMA(int Pages, int MaxBits, tPAddr *PhysAddr)
 }
 
 /**
- * \fn void MM_UnmapHWPage(tVAddr VAddr, Uint Number)
+ * \fn void MM_UnmapHWPages(tVAddr VAddr, Uint Number)
  * \brief Unmap a hardware page
  */
-void MM_UnmapHWPage(tVAddr VAddr, Uint Number)
+void MM_UnmapHWPages(tVAddr VAddr, Uint Number)
 {
         int    i, j;
        // Sanity Check
@@ -1022,6 +1022,6 @@ void MM_UnmapHWPage(tVAddr VAddr, Uint Number)
 EXPORT(MM_GetPhysAddr);
 EXPORT(MM_Map);
 //EXPORT(MM_Unmap);
-EXPORT(MM_MapHWPage);
+EXPORT(MM_MapHWPages);
 EXPORT(MM_AllocDMA);
-EXPORT(MM_UnmapHWPage);
+EXPORT(MM_UnmapHWPages);
index a66a540..3b5ceb2 100644 (file)
@@ -4,6 +4,7 @@
  */
 #include <acess.h>
 #include <proc.h>
+#include <desctab.h>
 #include <mm_virt.h>
 #include <errno.h>
 #if USE_MP
 
 // === CONSTANTS ===
 #define        SWITCH_MAGIC    0xFFFACE55      // There is no code in this area
+// Base is 1193182
 #define TIMER_DIVISOR  11931   //~100Hz
 
 // === IMPORTS ===
 extern tGDT    gGDT[];
+extern tIDT    gIDT[];
 extern void APStartup();       // 16-bit AP startup code
 extern Uint    GetEIP();       // start.asm
 extern Uint32  gaInitPageDir[1024];    // start.asm
@@ -35,7 +38,7 @@ extern tThread        *gDeleteThreads;
 extern tThread *Threads_GetNextToRun(int CPU);
 extern void    Threads_Dump();
 extern tThread *Threads_CloneTCB(Uint *Err, Uint Flags);
-extern void    Isr7();
+extern void    Isr8(); // Double Fault
 
 // === PROTOTYPES ===
 void   ArchThreads_Init();
@@ -47,6 +50,7 @@ void  Proc_Start();
 tThread        *Proc_GetCurThread();
 void   Proc_ChangeStack();
  int   Proc_Clone(Uint *Err, Uint Flags);
+void   Proc_StartProcess(Uint16 SS, Uint Stack, Uint Flags, Uint16 CS, Uint IP);
 void   Proc_Scheduler();
 
 // === GLOBALS ===
@@ -70,7 +74,12 @@ char gaDoubleFaultStack[1024];
 tTSS   gDoubleFault_TSS = {
        .ESP0 = (Uint)&gaDoubleFaultStack[1023],
        .SS0 = 0x10,
-       .EIP = (Uint)Isr7
+       .CR3 = (Uint)gaInitPageDir - KERNEL_BASE,
+       .EIP = (Uint)Isr8,
+       .ESP = (Uint)&gaDoubleFaultStack[1023],
+       .CS = 0x08,     .SS = 0x10,
+       .DS = 0x10,     .ES = 0x10,
+       .FS = 0x10,     .GS = 0x10,
 };
 
 // === CODE ===
@@ -275,6 +284,17 @@ void ArchThreads_Init()
        gGDT[5].BaseMid = (Uint)&gDoubleFault_TSS >> 16;
        gGDT[5].BaseHi = (Uint)&gDoubleFault_TSS >> 24;
        
+       Log_Debug("Proc", "gIDT[8] = {OffsetLo:%04x, CS:%04x, Flags:%04x, OffsetHi:%04x}", 
+               gIDT[8].OffsetLo, gIDT[8].CS, gIDT[8].Flags, gIDT[8].OffsetHi);
+       gIDT[8].OffsetLo = 0;
+       gIDT[8].CS = 5<<3;
+       gIDT[8].Flags = 0x8500;
+       gIDT[8].OffsetHi = 0;
+       Log_Debug("Proc", "gIDT[8] = {OffsetLo:%04x, CS:%04x, Flags:%04x, OffsetHi:%04x}", 
+               gIDT[8].OffsetLo, gIDT[8].CS, gIDT[8].Flags, gIDT[8].OffsetHi);
+       
+       //__asm__ __volatile__ ("xchg %bx, %bx");
+       
        #if USE_MP
        // Initialise Normal TSS(s)
        for(pos=0;pos<giNumCPUs;pos++)
@@ -601,13 +621,18 @@ void Proc_StartUser(Uint Entrypoint, Uint *Bases, int ArgC, char **ArgV, char **
        while(*Bases)
                *--stack = *Bases++;
        *--stack = 0;   // Return Address
-       delta = (Uint)stack;    // Reuse delta to save SP
        
-       *--stack = ss;          //Stack Segment
-       *--stack = delta;       //Stack Pointer
-       *--stack = 0x0202;      //EFLAGS (Resvd (0x2) and IF (0x20))
-       *--stack = cs;          //Code Segment
-       *--stack = Entrypoint;  //EIP
+       Proc_StartProcess(ss, (Uint)stack, 0x202, cs, Entrypoint);
+}
+
+void Proc_StartProcess(Uint16 SS, Uint Stack, Uint Flags, Uint16 CS, Uint IP)
+{
+       Uint    *stack = (void*)Stack;
+       *--stack = SS;          //Stack Segment
+       *--stack = Stack;       //Stack Pointer
+       *--stack = Flags;       //EFLAGS (Resvd (0x2) and IF (0x20))
+       *--stack = CS;          //Code Segment
+       *--stack = IP;  //EIP
        //PUSHAD
        *--stack = 0xAAAAAAAA;  // eax
        *--stack = 0xCCCCCCCC;  // ecx
@@ -618,10 +643,10 @@ void Proc_StartUser(Uint Entrypoint, Uint *Bases, int ArgC, char **ArgV, char **
        *--stack = 0x51515151;  // esi
        *--stack = 0xB4B4B4B4;  // ebp
        //Individual PUSHs
-       *--stack = ss;  // ds
-       *--stack = ss;  // es
-       *--stack = ss;  // fs
-       *--stack = ss;  // gs
+       *--stack = SS;  // ds
+       *--stack = SS;  // es
+       *--stack = SS;  // fs
+       *--stack = SS;  // gs
        
        __asm__ __volatile__ (
        "mov %%eax,%%esp;\n\t"  // Set stack pointer
index f1d1ea7..d9a1e50 100644 (file)
@@ -5,6 +5,9 @@
 \r
 KERNEL_BASE    equ 0xC0000000\r
 \r
+[extern __load_addr]\r
+[extern __bss_start]\r
+[extern gKernelEnd]\r
 [section .multiboot]\r
 mboot:\r
     ; Multiboot macros to make a few lines later more readable\r
@@ -20,6 +23,37 @@ mboot:
     dd MULTIBOOT_CHECKSUM\r
        dd mboot - KERNEL_BASE  ;Location of Multiboot Header\r
        \r
+; Multiboot 2 Header\r
+mboot2:\r
+    MULTIBOOT2_HEADER_MAGIC    equ 0xE85250D6\r
+    MULTIBOOT2_HEADER_ARCH     equ 0\r
+    MULTIBOOT2_HEADER_LENGTH   equ (mboot2_end-mboot2)\r
+    MULTIBOOT2_CHECKSUM        equ -(MULTIBOOT2_HEADER_MAGIC + MULTIBOOT2_HEADER_ARCH + MULTIBOOT2_HEADER_LENGTH)\r
+       \r
+    dd MULTIBOOT2_HEADER_MAGIC\r
+    dd MULTIBOOT2_HEADER_ARCH\r
+    dd MULTIBOOT2_HEADER_LENGTH\r
+    dd MULTIBOOT2_CHECKSUM\r
+       ; MBoot2 Address Header\r
+       dw      2, 0\r
+       dd      8 + 16\r
+       dd      mboot2  ; Location of Multiboot Header\r
+       dd      __load_addr - KERNEL_BASE       ; Kernel Load base\r
+       dd      __bss_start - KERNEL_BASE       ; Kernel Data End\r
+       dd      gKernelEnd - KERNEL_BASE        ; Kernel BSS End\r
+       ; MBoot2 Entry Point Tag\r
+       dw      3, 0\r
+       dd      8 + 4\r
+       dd      start - KERNEL_BASE\r
+       ; MBoot2 Module Alignment Tag\r
+       dw      6, 0\r
+       dd      12      ; ???\r
+       dd      0       ; Search me, seems it wants padding\r
+       ; Terminator\r
+       dw      0, 0\r
+       dd      8\r
+mboot2_end:\r
+       \r
 [section .text]\r
 [extern kmain]\r
 [global start]\r
@@ -114,6 +148,26 @@ GetEIP:
        mov eax, [esp]\r
        ret\r
 \r
+; int CallWithArgArray(void *Ptr, int NArgs, Uint *Args)\r
+; Call a function passing the array as arguments\r
+[global CallWithArgArray]\r
+CallWithArgArray:\r
+       push ebp\r
+       mov ebp, esp\r
+       mov ecx, [ebp+12]       ; Get NArgs\r
+       mov edx, [ebp+16]\r
+\r
+.top:\r
+       mov eax, [edx+ecx*4-4]\r
+       push eax\r
+       loop .top\r
+       \r
+       mov eax, [ebp+8]\r
+       call eax\r
+       lea esp, [ebp]\r
+       pop ebp\r
+       ret\r
+\r
 [extern Proc_Clone]\r
 [extern Threads_Exit]\r
 [global SpawnTask]\r
diff --git a/Kernel/arch/x86/vm8086.c b/Kernel/arch/x86/vm8086.c
new file mode 100644 (file)
index 0000000..8ef7453
--- /dev/null
@@ -0,0 +1,375 @@
+/*
+ * Acess2 VM8086 Driver
+ * - By John Hodge (thePowersGang)
+ */
+#include <acess.h>
+#include <vm8086.h>
+#include <modules.h>
+
+// === CONSTANTS ===
+#define VM8086_MAGIC_CS        0xFFFF
+#define VM8086_MAGIC_IP        0x0010
+#define VM8086_STACK_SEG       0x9F00
+#define VM8086_STACK_OFS       0x0AFE
+enum eVM8086_Opcodes
+{
+       VM8086_OP_PUSHF = 0x9C,
+       VM8086_OP_POPF  = 0x9D,
+       VM8086_OP_INT_I = 0xCD,
+       VM8086_OP_IRET  = 0xCF,
+       VM8086_OP_IN_AD = 0xEC,
+       VM8086_OP_IN_ADX= 0xED
+};
+#define VM8086_PAGES_PER_INST  4
+
+// === IMPORTS ===
+ int   Proc_Clone(Uint *Err, Uint Flags);
+
+// === TYPES ===
+struct sVM8086_InternalData
+{
+       struct {
+               Uint32  Bitmap; // 32 sections = 128 byte blocks
+               tVAddr  VirtBase;
+               tPAddr  PhysAddr;
+       }       AllocatedPages[VM8086_PAGES_PER_INST];
+};
+
+// === PROTOTYPES ===
+ int   VM8086_Install(char **Arguments);
+void   VM8086_GPF(tRegs *Regs);
+tVM8086        *VM8086_Init(void);
+
+// === GLOBALS ===
+MODULE_DEFINE(0, 0x100, VM8086, VM8086_Install, NULL, NULL);
+tSpinlock      glVM8086_Process;
+tPID   gVM8086_WorkerPID;
+tTID   gVM8086_CallingThread;
+tVM8086        * volatile gpVM8086_State;
+
+// === FUNCTIONS ===
+int VM8086_Install(char **Arguments)
+{
+       tPID    pid;    
+       
+       // Create BIOS Call process
+       pid = Proc_Clone(NULL, CLONE_VM);
+       if(pid == -1)
+       {
+               Log_Error("VM8086", "Unable to clone kernel into VM8086 worker");
+               return MODULE_ERR_MISC;
+       }
+       if(pid == 0)
+       {
+               Uint    *stacksetup;    // Initialising Stack
+               Uint16  *rmstack;       // Real Mode Stack
+                int    i;
+                
+               // Set Image Name
+               Threads_SetName("VM8086");
+               
+               // Map ROM Area
+               for(i=0xA0;i<0x100;i++) {
+                       MM_Map( i * 0x1000, i * 0x1000 );
+                       //MM_SetFlags( i * 0x1000, MM_PFLAG_RO, MM_PFLAG_RO );  // Set Read Only
+               }
+               MM_Map( 0, 0 ); // IVT / BDA
+               for(i=0x10;i<0x9F;i++) {
+                       MM_Map( i * 0x1000, i * 0x1000 );       MM_DerefPhys( i * 0x1000 );
+               }
+               MM_Map( 0x9F000, 0x9F000 );     // Stack / EBDA
+               MM_Allocate( 0x100000 );        // System Stack / Stub
+               
+               *(Uint8*)(0x100000) = VM8086_OP_IRET;
+               *(Uint8*)(0x100001) = 0x07;     // POP ES
+               *(Uint8*)(0x100002) = 0x1F;     // POP DS
+               *(Uint8*)(0x100003) = 0xCB;     // RET FAR
+               
+               rmstack = (Uint16*)(VM8086_STACK_SEG*16 + VM8086_STACK_OFS);
+               *rmstack-- = 0xFFFF;    //CS
+               *rmstack-- = 0x0010;    //IP
+               
+               // Setup Stack
+               stacksetup = (Uint*)0x101000;
+               *--stacksetup = VM8086_STACK_SEG;       // GS
+               *--stacksetup = VM8086_STACK_SEG;       // FS
+               *--stacksetup = VM8086_STACK_SEG;       // DS
+               *--stacksetup = VM8086_STACK_SEG;       // ES
+               *--stacksetup = VM8086_STACK_SEG;       // SS
+               *--stacksetup = VM8086_STACK_OFS-2;     // SP
+               *--stacksetup = 0x20202;        // FLAGS
+               *--stacksetup = 0xFFFF; // CS
+               *--stacksetup = 0x10;   // IP
+               *--stacksetup = 0xAAAA; // AX
+               *--stacksetup = 0xCCCC; // CX
+               *--stacksetup = 0xDDDD; // DX
+               *--stacksetup = 0xBBBB; // BX
+               *--stacksetup = 0x5454; // SP
+               *--stacksetup = 0xB4B4; // BP
+               *--stacksetup = 0x5151; // SI
+               *--stacksetup = 0xD1D1; // DI
+               *--stacksetup = 0x20|3; // DS - Kernel
+               *--stacksetup = 0x20|3; // ES - Kernel
+               *--stacksetup = 0x20|3; // FS
+               *--stacksetup = 0x20|3; // GS
+               __asm__ __volatile__ (
+               "mov %%eax,%%esp;\n\t"  // Set stack pointer
+               "pop %%gs;\n\t"
+               "pop %%fs;\n\t"
+               "pop %%es;\n\t"
+               "pop %%ds;\n\t"
+               "popa;\n\t"
+               "iret;\n\t" : : "a" (stacksetup));
+               for(;;);        // Shouldn't be reached
+       }
+       
+       gVM8086_WorkerPID = pid;
+       Log_Log("VM8086", "gVM8086_WorkerPID = %i", pid);
+       Threads_Yield();        // Yield to allow the child to initialise
+       
+       return MODULE_ERR_OK;
+}
+
+void VM8086_GPF(tRegs *Regs)
+{
+       Uint8   opcode;
+       
+       //Log_Log("VM8086", "GPF - %04x:%04x", Regs->cs, Regs->eip);
+       
+       if(Regs->eip == VM8086_MAGIC_IP && Regs->cs == VM8086_MAGIC_CS
+       && Threads_GetPID() == gVM8086_WorkerPID)
+       {
+               if( gpVM8086_State ) {
+                       gpVM8086_State->AX = Regs->eax; gpVM8086_State->CX = Regs->ecx;
+                       gpVM8086_State->DX = Regs->edx; gpVM8086_State->BX = Regs->ebx;
+                       gpVM8086_State->BP = Regs->ebp;
+                       gpVM8086_State->SI = Regs->esi; gpVM8086_State->DI = Regs->edi;
+                       gpVM8086_State->DS = Regs->ds;  gpVM8086_State->ES = Regs->es;
+                       gpVM8086_State = NULL;
+                       Threads_WakeTID(gVM8086_CallingThread);
+               }
+               
+               //Log_Log("VM8086", "Waiting for something to do");
+               __asm__ __volatile__ ("sti");
+               // Wait for a new task
+               while(!gpVM8086_State) {
+                       Threads_Sleep();
+                       //Log_Log("VM8086", "gpVM8086_State = %p", gpVM8086_State);
+               }
+               
+               //Log_Log("VM8086", "We have a task (%p)", gpVM8086_State);
+               Regs->esp -= 2; *(Uint16*)( (Regs->ss<<4) + (Regs->esp&0xFFFF) ) = VM8086_MAGIC_CS;
+               Regs->esp -= 2; *(Uint16*)( (Regs->ss<<4) + (Regs->esp&0xFFFF) ) = VM8086_MAGIC_IP;
+               Regs->esp -= 2; *(Uint16*)( (Regs->ss<<4) + (Regs->esp&0xFFFF) ) = gpVM8086_State->CS;
+               Regs->esp -= 2; *(Uint16*)( (Regs->ss<<4) + (Regs->esp&0xFFFF) ) = gpVM8086_State->IP;
+               Regs->esp -= 2; *(Uint16*)( (Regs->ss<<4) + (Regs->esp&0xFFFF) ) = gpVM8086_State->DS;
+               Regs->esp -= 2; *(Uint16*)( (Regs->ss<<4) + (Regs->esp&0xFFFF) ) = gpVM8086_State->ES;
+               
+               // Set Registers
+               Regs->eip = 0x11;       Regs->cs = 0xFFFF;
+               Regs->eax = gpVM8086_State->AX; Regs->ecx = gpVM8086_State->CX;
+               Regs->edx = gpVM8086_State->DX; Regs->ebx = gpVM8086_State->BX;
+               Regs->esi = gpVM8086_State->SI; Regs->edi = gpVM8086_State->DI;
+               Regs->ebp = gpVM8086_State->BP;
+               Regs->ds = 0x23;        Regs->es = 0x23;
+               Regs->fs = 0x23;        Regs->gs = 0x23;
+               return ;
+       }
+       
+       opcode = *(Uint8*)( KERNEL_BASE + (Regs->cs*16) + (Regs->eip) );
+       Regs->eip ++;
+       switch(opcode)
+       {
+       case VM8086_OP_PUSHF:   //PUSHF
+               Regs->esp -= 2;
+               *(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) ) = Regs->eflags & 0xFFFF;
+               #if TRACE_EMU
+               Log_Debug("VM8086", "Emulated PUSHF");
+               #endif
+               break;
+       case VM8086_OP_POPF:    //POPF
+               Regs->eflags &= 0xFFFF0002;
+               Regs->eflags |= *(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) ) & 0xFFFD;        // Changing IF is not allowed
+               Regs->esp += 2;
+               #if TRACE_EMU
+               Log_Debug("VM8086", "Emulated POPF");
+               #endif
+               break;
+       
+       case VM8086_OP_INT_I:   //INT imm8
+               {
+                int    id;
+               id = *(Uint8*)( Regs->cs*16 +(Regs->eip&0xFFFF));
+               Regs->eip ++;
+               
+               Regs->esp -= 2; *(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) ) = Regs->cs;
+               Regs->esp -= 2; *(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) ) = Regs->eip;
+               
+               Regs->cs = *(Uint16*)(4*id + 2);
+               Regs->eip = *(Uint16*)(4*id);
+               #if TRACE_EMU
+               Log_Debug("VM8086", "Emulated INT 0x%x", id);
+               #endif
+               }
+               break;
+       
+       case VM8086_OP_IRET:    //IRET
+               Regs->eip = *(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) );     Regs->esp += 2;
+               Regs->cs  = *(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) );     Regs->esp += 2;
+               #if TRACE_EMU
+               Log_Debug("VM8086", "IRET to %04x:%04x", Regs->cs, Regs->eip);
+               #endif
+               break;
+       
+       
+       case VM8086_OP_IN_AD:   //IN AL, DX
+               Regs->eax &= 0xFFFFFF00;
+               Regs->eax |= inb(Regs->edx&0xFFFF);
+               #if TRACE_EMU
+               Log_Debug("VM8086", "Emulated IN AL, DX (Port 0x%x)\n", Regs->edx&0xFFFF);
+               #endif
+               break;
+       case VM8086_OP_IN_ADX:  //IN AX, DX
+               Regs->eax &= 0xFFFF0000;
+               Regs->eax |= inw(Regs->edx&0xFFFF);
+               #if TRACE_EMU
+               Log_Debug("VM8086", "Emulated IN AX, DX (Port 0x%x)\n", Regs->edx&0xFFFF);
+               #endif
+               break;
+               
+       case 0xEE:      //OUT DX, AL
+               outb(Regs->edx&0xFFFF, Regs->eax&0xFF);
+               #if TRACE_EMU
+               Log_Debug("VM8086", "Emulated OUT DX, AL (*0x%04x = 0x%02x)\n", Regs->edx&0xFFFF, Regs->eax&0xFF);
+               #endif
+               break;
+       case 0xEF:      //OUT DX, AX
+               outw(Regs->edx&0xFFFF, Regs->eax&0xFFFF);
+               #if TRACE_EMU
+               Log_Debug("VM8086", "Emulated OUT DX, AX (*0x%04x = 0x%04x)\n", Regs->edx&0xFFFF, Regs->eax&0xFFFF);
+               #endif
+               break;
+               
+       // TODO: Decide on allowing VM8086 Apps to enable/disable interrupts
+       case 0xFA:      //CLI
+               break;
+       case 0xFB:      //STI
+               break;
+       
+       case 0x66:
+               Log_Warning("VM8086", "Code at %04x:%04x attempted to use an operand override, ignored",
+                       Regs->cs, Regs->eip);
+               break;
+       
+       default:
+               Log_Error("VM8086", "Error - Unknown opcode %02x caused a GPF at %04x:%04x",
+                       opcode, Regs->cs, Regs->eip);
+               // Force an end to the call
+               Regs->cs = VM8086_MAGIC_CS;
+               Regs->eip = VM8086_MAGIC_IP;
+               break;
+       }
+}
+
+/**
+ * \brief Create an instance of the VM8086 Emulator
+ */
+tVM8086 *VM8086_Init(void)
+{
+       tVM8086 *ret;
+       ret = calloc( 1, sizeof(tVM8086) + sizeof(struct sVM8086_InternalData) );
+       ret->Internal = (void*)((tVAddr)ret + sizeof(tVM8086));
+       return ret;
+}
+
+void VM8086_Free(tVM8086 *State)
+{
+        int    i;
+       for( i = VM8086_PAGES_PER_INST; i --; )
+               MM_UnmapHWPages( State->Internal->AllocatedPages[i].VirtBase, 1);
+       free(State);
+}
+
+void *VM8086_Allocate(tVM8086 *State, int Size, Uint16 *Segment, Uint16 *Offset)
+{
+        int    i, j, base = 0;
+        int    nBlocks, rem;
+       
+       Size = (Size + 127) & ~127;
+       nBlocks = Size / 128;
+       
+       if(Size > 4096) return NULL;
+       
+       for( i = 0; i < VM8086_PAGES_PER_INST; i++ )
+       {
+               if( State->Internal->AllocatedPages[i].VirtBase == 0 )  continue;
+               
+               
+               //Log_Debug("VM8086", "AllocatedPages[%i].Bitmap = 0b%b", i, State->Internal->AllocatedPages[i].Bitmap);
+               
+               rem = nBlocks;
+               base = 0;
+               // Scan the bitmap for a free block
+               for( j = 0; j < 32; j++ ) {
+                       if( State->Internal->AllocatedPages[i].Bitmap & (1 << j) ) {
+                               base = j;
+                               rem = nBlocks;
+                       }
+                       else {
+                               rem --;
+                               if(rem == 0)    // Goodie, there's a gap
+                               {
+                                       for( j = 0; j < nBlocks; j++ )
+                                               State->Internal->AllocatedPages[i].Bitmap |= 1 << (base + j);
+                                       *Segment = State->Internal->AllocatedPages[i].PhysAddr / 16 + base * 8;
+                                       *Offset = 0;
+                                       //Log_Debug("VM8086", "Allocated at #%i,%04x", i, base*128);
+                                       return (void*)( State->Internal->AllocatedPages[i].VirtBase + base * 128 );
+                               }
+                       }
+               }
+       }
+       
+       // No pages with free space?, allocate a new one
+       for( i = 0; i < VM8086_PAGES_PER_INST; i++ )
+       {
+               if( State->Internal->AllocatedPages[i].VirtBase == 0 )  break;
+       }
+       // Darn, we can't allocate any more
+       if( i == VM8086_PAGES_PER_INST ) {
+               Log_Warning("VM8086", "Out of pages in %p", State);
+               return NULL;
+       }
+       
+       State->Internal->AllocatedPages[i].VirtBase = MM_AllocDMA(
+               1, 20, &State->Internal->AllocatedPages[i].PhysAddr);
+       State->Internal->AllocatedPages[i].Bitmap = 0;
+               
+       for( j = 0; j < nBlocks; j++ )
+               State->Internal->AllocatedPages[i].Bitmap |= 1 << j;
+       //Log_Debug("VM8086", "AllocatedPages[%i].Bitmap = 0b%b", i, State->Internal->AllocatedPages[i].Bitmap);
+       *Segment = State->Internal->AllocatedPages[i].PhysAddr / 16;
+       *Offset = 0;
+       return (void*) State->Internal->AllocatedPages[i].VirtBase;
+}
+
+void *VM8086_GetPointer(tVM8086 *State, Uint16 Segment, Uint16 Offset)
+{
+       return (void*)( KERNEL_BASE + Segment*16 + Offset );
+}
+
+void VM8086_Int(tVM8086 *State, Uint8 Interrupt)
+{
+       State->IP = *(Uint16*)(KERNEL_BASE+4*Interrupt);
+       State->CS = *(Uint16*)(KERNEL_BASE+4*Interrupt+2);
+       
+       LOCK( &glVM8086_Process );
+       
+       gpVM8086_State = State;
+       gVM8086_CallingThread = Threads_GetTID();
+       Threads_WakeTID( gVM8086_WorkerPID );
+       while( gpVM8086_State != NULL )
+               Threads_Sleep();
+       
+       RELEASE( &glVM8086_Process );
+}
index 4bc13b1..ad8edb0 100644 (file)
@@ -57,7 +57,12 @@ tBinary *Elf_Load(int fp)
        }\r
        \r
        // Read Program Header Table\r
-       phtab = malloc(sizeof(Elf32_Phdr)*hdr.phentcount);\r
+       phtab = malloc( sizeof(Elf32_Phdr) * hdr.phentcount );\r
+       if( !phtab ) {\r
+               LEAVE('n');\r
+               return NULL;\r
+       }\r
+       LOG("hdr.phoff = 0x%08x", hdr.phoff);\r
        VFS_Seek(fp, hdr.phoff, SEEK_SET);\r
        VFS_Read(fp, sizeof(Elf32_Phdr)*hdr.phentcount, phtab);\r
        \r
@@ -88,7 +93,17 @@ tBinary *Elf_Load(int fp)
        for( i = 0; i < hdr.phentcount; i++ )\r
        {\r
                 int    lastSize;\r
-               LOG("phtab[%i].Type = 0x%x", i, phtab[i].Type);\r
+               //LOG("phtab[%i].Type = 0x%x", i, phtab[i].Type);\r
+               LOG("phtab[%i] = {", i);\r
+               LOG(" .Type = 0x%08x", phtab[i].Type);\r
+               LOG(" .Offset = 0x%08x", phtab[i].Offset);\r
+               LOG(" .VAddr = 0x%08x", phtab[i].VAddr);\r
+               LOG(" .PAddr = 0x%08x", phtab[i].PAddr);\r
+               LOG(" .FileSize = 0x%08x", phtab[i].FileSize);\r
+               LOG(" .MemSize = 0x%08x", phtab[i].MemSize);\r
+               LOG(" .Flags = 0x%08x", phtab[i].Flags);\r
+               LOG(" .Align = 0x%08x", phtab[i].Align);\r
+               LOG(" }");\r
                // Get Interpreter Name\r
                if( phtab[i].Type == PT_INTERP )\r
                {\r
index 1ff2128..13724eb 100644 (file)
@@ -130,9 +130,9 @@ enum {
 \r
 struct sElf32_Phdr {\r
        Uint32  Type;\r
-       Uint    Offset;\r
-       Uint    VAddr;\r
-       Uint    PAddr;\r
+       Uint32  Offset;\r
+       Uint32  VAddr;\r
+       Uint32  PAddr;\r
        Uint32  FileSize;\r
        Uint32  MemSize;\r
        Uint32  Flags;\r
index e7967e8..0b74529 100644 (file)
@@ -29,7 +29,7 @@ tBinaryType   gPE_Loader = {
 int PE_Install(char **Arguments)\r
 {\r
        Binary_RegisterType(&gPE_Loader);\r
-       return 1;\r
+       return MODULE_ERR_OK;\r
 }\r
 \r
 /**\r
index b02ca6e..77309f3 100644 (file)
@@ -24,7 +24,6 @@ typedef struct sKernelBin {
 \r
 // === IMPORTS ===\r
 extern int     Proc_Clone(Uint *Err, Uint Flags);\r
-extern void    Threads_SetName(char *Name);\r
 extern char    *Threads_GetName(int ID);\r
 extern void    Threads_Exit(int, int);\r
 extern Uint    MM_ClearUser();\r
@@ -190,7 +189,7 @@ Uint Binary_Load(char *file, Uint *entryPoint)
        sTruePath = VFS_GetTruePath(file);\r
        \r
        if(sTruePath == NULL) {\r
-               Warning("[BIN ] '%s' does not exist.", file);\r
+               Warning("[BIN  ] '%s' does not exist.", file);\r
                LEAVE('x', 0);\r
                return 0;\r
        }\r
index be93716..4b3aeb7 100644 (file)
@@ -52,7 +52,7 @@ int getDebugChar()
        return inb(GDB_SERIAL_PORT);
 }
 
-static void E9(char ch)
+static void Debug_Putchar(char ch)
 {
        if(giDebug_KTerm != -1)
                VFS_Write(giDebug_KTerm, 1, &ch);
@@ -77,25 +77,26 @@ static void E9(char ch)
        #endif
 }
 
-static void E9_Str(char *Str)
+static void Debug_Puts(char *Str)
 {
-       while(*Str)     E9(*Str++);
+       while(*Str)     Debug_Putchar(*Str++);
 }
 
-void E9_Fmt(const char *format, va_list *args)
+void Debug_Fmt(const char *format, va_list *args)
 {
        char    c, pad = ' ';
-        int    minSize = 0;
+        int    minSize = 0, len;
        char    tmpBuf[34];     // For Integers
        char    *p = NULL;
         int    isLongLong = 0;
        Uint64  arg;
+        int    bPadLeft = 0;
 
        while((c = *format++) != 0)
        {
                // Non control character
                if( c != '%' ) {
-                       E9(c);
+                       Debug_Putchar(c);
                        continue;
                }
 
@@ -103,14 +104,14 @@ void E9_Fmt(const char *format, va_list *args)
 
                // Literal %
                if(c == '%') {
-                       E9('%');
+                       Debug_Putchar('%');
                        continue;
                }
 
                // Pointer
                if(c == 'p') {
                        Uint    ptr = va_arg(*args, Uint);
-                       E9('*');        E9('0');        E9('x');
+                       Debug_Putchar('*');     Debug_Putchar('0');     Debug_Putchar('x');
                        p = tmpBuf;
                        itoa(p, ptr, 16, BITS/4, '0');
                        goto printString;
@@ -119,6 +120,12 @@ void E9_Fmt(const char *format, va_list *args)
                // Get Argument
                arg = va_arg(*args, Uint);
 
+               // - Padding Side Flag
+               if(c == '+') {
+                       bPadLeft = 1;
+                       c = *format++;
+               }
+
                // Padding
                if(c == '0') {
                        pad = '0';
@@ -157,7 +164,7 @@ void E9_Fmt(const char *format, va_list *args)
                case 'd':
                case 'i':
                        if( (isLongLong && arg >> 63) || (!isLongLong && arg >> 31) ) {
-                               E9('-');
+                               Debug_Putchar('-');
                                arg = -arg;
                        }
                        itoa(p, arg, 10, minSize, pad);
@@ -175,43 +182,43 @@ void E9_Fmt(const char *format, va_list *args)
                        itoa(p, arg, 2, minSize, pad);
                        goto printString;
 
+               printString:
+                       if(!p)          p = "(null)";
+                       while(*p)       Debug_Putchar(*p++);
+                       break;
+
                case 'B':       //Boolean
-                       if(arg) E9_Str("True");
-                       else    E9_Str("False");
+                       if(arg) Debug_Puts("True");
+                       else    Debug_Puts("False");
                        break;
 
                case 's':
                        p = (char*)(Uint)arg;
-               printString:
                        if(!p)          p = "(null)";
-                       while(*p)       E9(*p++);
+                       len = strlen(p);
+                       if( !bPadLeft ) while(len++ < minSize)  Debug_Putchar(pad);
+                       while(*p)       Debug_Putchar(*p++);
+                       if( bPadLeft )  while(len++ < minSize)  Debug_Putchar(pad);
                        break;
 
                // Single Character / Array
                case 'c':
                        if(minSize == 1) {
-                               E9(arg);
+                               Debug_Putchar(arg);
                                break;
                        }
                        p = (char*)(Uint)arg;
                        if(!p)  goto printString;
-                       while(minSize--)        E9(*p++);
+                       while(minSize--)        Debug_Putchar(*p++);
                        break;
 
-               default:        E9(arg);        break;
+               default:
+                       Debug_Putchar(arg);
+                       break;
                }
     }
 }
 
-/**
- * \fn void LogV(char *Fmt, va_list Args)
- */
-void LogV(char *Fmt, va_list Args)
-{
-       E9_Str("Log: ");
-       E9_Fmt(Fmt, &Args);
-       E9('\n');
-}
 /**
  * \fn void LogF(char *Msg, ...)
  */
@@ -221,7 +228,7 @@ void LogF(char *Fmt, ...)
 
        va_start(args, Fmt);
 
-       E9_Fmt(Fmt, &args);
+       Debug_Fmt(Fmt, &args);
 
        va_end(args);
 }
@@ -232,29 +239,29 @@ void Log(char *Fmt, ...)
 {
        va_list args;
 
-       E9_Str("Log: ");
+       Debug_Puts("Log: ");
        va_start(args, Fmt);
-       E9_Fmt(Fmt, &args);
+       Debug_Fmt(Fmt, &args);
        va_end(args);
-       E9('\n');
+       Debug_Putchar('\n');
 }
 void Warning(char *Fmt, ...)
 {
        va_list args;
-       E9_Str("Warning: ");
+       Debug_Puts("Warning: ");
        va_start(args, Fmt);
-       E9_Fmt(Fmt, &args);
+       Debug_Fmt(Fmt, &args);
        va_end(args);
-       E9('\n');
+       Debug_Putchar('\n');
 }
 void Panic(char *Fmt, ...)
 {
        va_list args;
-       E9_Str("Panic: ");
+       Debug_Puts("Panic: ");
        va_start(args, Fmt);
-       E9_Fmt(Fmt, &args);
+       Debug_Fmt(Fmt, &args);
        va_end(args);
-       E9('\n');
+       Debug_Putchar('\n');
 
        Threads_Dump();
 
@@ -268,7 +275,7 @@ void Debug_SetKTerminal(char *File)
        if(giDebug_KTerm != -1)
                VFS_Close(giDebug_KTerm);
        giDebug_KTerm = VFS_Open(File, VFS_OPENFLAG_WRITE);
-       Log("Opened '%s' as 0x%x", File, giDebug_KTerm);
+       Log_Log("Debug", "Opened '%s' as 0x%x", File, giDebug_KTerm);
 }
 
 void Debug_Enter(char *FuncName, char *ArgTypes, ...)
@@ -279,33 +286,33 @@ void Debug_Enter(char *FuncName, char *ArgTypes, ...)
 
        va_start(args, ArgTypes);
 
-       while(i--)      E9(' ');
+       while(i--)      Debug_Putchar(' ');
 
-       E9_Str(FuncName);       E9_Str(": (");
+       Debug_Puts(FuncName);   Debug_Puts(": (");
 
        while(*ArgTypes)
        {
                pos = strpos(ArgTypes, ' ');
                if(pos != -1)   ArgTypes[pos] = '\0';
                if(pos == -1 || pos > 1) {
-                       E9_Str(ArgTypes+1);
-                       E9('=');
+                       Debug_Puts(ArgTypes+1);
+                       Debug_Putchar('=');
                }
                if(pos != -1)   ArgTypes[pos] = ' ';
                switch(*ArgTypes)
                {
-               case 'p':       E9_Fmt("%p", &args);    break;
-               case 's':       E9_Fmt("'%s'", &args);  break;
-               case 'i':       E9_Fmt("%i", &args);    break;
-               case 'u':       E9_Fmt("%u", &args);    break;
-               case 'x':       E9_Fmt("0x%x", &args);  break;
-               case 'b':       E9_Fmt("0b%b", &args);  break;
+               case 'p':       Debug_Fmt("%p", &args); break;
+               case 's':       Debug_Fmt("'%s'", &args);       break;
+               case 'i':       Debug_Fmt("%i", &args); break;
+               case 'u':       Debug_Fmt("%u", &args); break;
+               case 'x':       Debug_Fmt("0x%x", &args);       break;
+               case 'b':       Debug_Fmt("0b%b", &args);       break;
                // Extended (64-Bit)
-               case 'X':       E9_Fmt("0x%llx", &args);        break;
-               case 'B':       E9_Fmt("0b%llb", &args);        break;
+               case 'X':       Debug_Fmt("0x%llx", &args);     break;
+               case 'B':       Debug_Fmt("0b%llb", &args);     break;
                }
                if(pos != -1) {
-                       E9(',');        E9(' ');
+                       Debug_Putchar(',');     Debug_Putchar(' ');
                }
 
                if(pos == -1)   break;
@@ -313,7 +320,7 @@ void Debug_Enter(char *FuncName, char *ArgTypes, ...)
        }
 
        va_end(args);
-       E9(')');        E9('\n');
+       Debug_Putchar(')');     Debug_Putchar('\n');
 }
 
 void Debug_Log(char *FuncName, char *Fmt, ...)
@@ -323,13 +330,13 @@ void Debug_Log(char *FuncName, char *Fmt, ...)
 
        va_start(args, Fmt);
 
-       while(i--)      E9(' ');
+       while(i--)      Debug_Putchar(' ');
 
-       E9_Str(FuncName);       E9_Str(": ");
-       E9_Fmt(Fmt, &args);
+       Debug_Puts(FuncName);   Debug_Puts(": ");
+       Debug_Fmt(Fmt, &args);
 
        va_end(args);
-       E9('\n');
+       Debug_Putchar('\n');
 }
 
 void Debug_Leave(char *FuncName, char RetType, ...)
@@ -344,29 +351,29 @@ void Debug_Leave(char *FuncName, char RetType, ...)
                i = 0;
        }
        // Indenting
-       while(i--)      E9(' ');
+       while(i--)      Debug_Putchar(' ');
 
-       E9_Str(FuncName);       E9_Str(": RETURN");
+       Debug_Puts(FuncName);   Debug_Puts(": RETURN");
 
        // No Return
        if(RetType == '-') {
-               E9('\n');
+               Debug_Putchar('\n');
                return;
        }
 
-       E9(' ');
+       Debug_Putchar(' ');
        switch(RetType)
        {
-       case 'n':       E9_Str("NULL"); break;
-       case 'p':       E9_Fmt("%p", &args);    break;
-       case 's':       E9_Fmt("'%s'", &args);  break;
-       case 'i':       E9_Fmt("%i", &args);    break;
-       case 'u':       E9_Fmt("%u", &args);    break;
-       case 'x':       E9_Fmt("0x%x", &args);  break;
+       case 'n':       Debug_Puts("NULL");     break;
+       case 'p':       Debug_Fmt("%p", &args); break;
+       case 's':       Debug_Fmt("'%s'", &args);       break;
+       case 'i':       Debug_Fmt("%i", &args); break;
+       case 'u':       Debug_Fmt("%u", &args); break;
+       case 'x':       Debug_Fmt("0x%x", &args);       break;
        // Extended (64-Bit)
-       case 'X':       E9_Fmt("0x%llx", &args);        break;
+       case 'X':       Debug_Fmt("0x%llx", &args);     break;
        }
-       E9('\n');
+       Debug_Putchar('\n');
 
        va_end(args);
 }
@@ -375,7 +382,7 @@ void Debug_HexDump(char *Header, void *Data, Uint Length)
 {
        Uint8   *cdat = Data;
        Uint    pos = 0;
-       E9_Str(Header);
+       Debug_Puts(Header);
        LogF(" (Hexdump of %p)\n", Data);
 
        while(Length >= 16)
@@ -403,7 +410,7 @@ void Debug_HexDump(char *Header, void *Data, Uint Length)
                Length--;
                cdat ++;
        }
-       E9('\n');
+       Debug_Putchar('\n');
 }
 
 // --- EXPORTS ---
index 9116703..1f356cd 100644 (file)
@@ -3,6 +3,7 @@
  * DMA Driver\r
  */\r
 #include <acess.h>\r
+#include <modules.h>\r
 \r
 #define DMA_SIZE       (0x2400)\r
 #define DMA_ADDRESS(c) ((c)*DMA_SIZE+0x500)    //Save Space for IDT and BDA\r
 #define HIB(x) (((x)>>8)&0xFF)\r
 #define HIW(x) (((x)>>16)&0xFFFF)\r
 \r
-typedef struct {\r
-       int     mode;\r
+// === TYPES ===\r
+typedef struct\r
+{\r
+        int    mode;\r
        char    *address;\r
 } t_dmaChannel;\r
 \r
+// === PROTOTYPES ===\r
+ int   DMA_Install();\r
+void   DMA_SetChannel(int Channel, int length, int read);\r
+ int   DMA_ReadData(int channel, int count, void *buffer);\r
+\r
+// === CONSTANTS ===\r
 const Uint8 cMASKPORT [8] = { 0x0A, 0x0A, 0x0A, 0x0A, 0xD4, 0xD4, 0xD4, 0xD4 };\r
 const Uint8 cMODEPORT [8] = { 0x0B, 0x0B, 0x0B, 0x0B, 0xD6, 0xD6, 0xD6, 0xD6 };\r
 const Uint8 cCLEARPORT[8] = { 0x0C, 0x0C, 0x0C, 0x0C, 0xD8, 0xD8, 0xD8, 0xD8 };\r
@@ -23,14 +32,17 @@ const Uint8 cPAGEPORT [8] = { 0x87, 0x83, 0x81, 0x82, 0x8F, 0x8B, 0x89, 0x8A };
 const Uint8 cADDRPORT [8] = { 0x00, 0x02, 0x04, 0x06, 0xC0, 0xC4, 0xC8, 0xCC };\r
 const Uint8 cCOUNTPORT[8] = { 0x01, 0x03, 0x05, 0x07, 0xC2, 0xC6, 0xCA, 0xCE };\r
 \r
+// === GLOBALS ===\r
+MODULE_DEFINE(0, 0x0100, ISADMA, DMA_Install, NULL, NULL);\r
 char   *dma_addresses[8];\r
 t_dmaChannel   dma_channels[8];\r
 \r
+// === CODE ===\r
 /**\r
- * \fn void DMA_Install()\r
+ * \fn int DMA_Install()\r
  * \brief Initialise DMA channels\r
  */\r
-void DMA_Install()\r
+int DMA_Install()\r
 {\r
        Uint    i;\r
        for(i=8;i--;)\r
@@ -51,6 +63,7 @@ void DMA_Install()
                dma_addresses[i] = (char*)DMA_ADDRESS(i);\r
                dma_addresses[i] += KERNEL_BASE;\r
        }\r
+       return MODULE_ERR_OK;\r
 }\r
 \r
 /**\r
@@ -92,3 +105,19 @@ int DMA_ReadData(int channel, int count, void *buffer)
        memcpy(buffer, dma_addresses[channel], count);\r
        return 0;\r
 }\r
+\r
+/**\r
+ * \fn void DMA_WriteData(int channel, int count, void *buffer)\r
+ * \brief Write data to a DMA buffer\r
+ */\r
+int DMA_WriteData(int channel, int count, void *buffer)\r
+{\r
+       if(channel < 0 || channel > 7)\r
+               return -1;\r
+       if(count < 0 || count > DMA_SIZE)\r
+               return -2;\r
+       \r
+       memcpy(dma_addresses[channel], buffer, count);\r
+       \r
+       return 0;\r
+}\r
index 7bb4ca3..67b9a6d 100644 (file)
@@ -62,7 +62,7 @@ tPipe *gFIFO_NamedPipes = NULL;
 int FIFO_Install(char **Options)
 {
        DevFS_AddDevice( &gFIFO_DriverInfo );
-       return MODULE_INIT_SUCCESS;
+       return MODULE_ERR_OK;
 }
 
 /**
index 92f00a7..6577882 100644 (file)
@@ -11,6 +11,7 @@
 
 // === CONSTANTS ===
 #define        KB_BUFFER_SIZE  1024
+#define        USE_KERNEL_MAGIC        1
 
 // === IMPORTS ===
 void   Threads_Dump();
@@ -63,11 +64,12 @@ int KB_Install(char **Arguments)
        temp = inb(0x61);
        outb(0x61, temp | 0x80);
        outb(0x61, temp & 0x7F);
+       inb(0x60);      // Clear keyboard buffer
        
        IRQ_AddHandler(1, KB_IRQHandler);
        DevFS_AddDevice( &gKB_DevInfo );
        //Log("KB_Install: Installed");
-       return 1;
+       return MODULE_ERR_OK;
 }
 
 /**
@@ -80,16 +82,16 @@ void KB_IRQHandler()
        Uint32  ch;
        // int  keyNum;
 
-       //if( inportb(0x64) & 0x20 )    return;
+       // Check port 0x64 to tell if this is from the aux port
+       //if( inb(0x64) & 0x20 )        return;
 
        scancode = inb(0x60); // Read from the keyboard's data buffer
-
-       //Log("KB_IRQHandler: scancode = 0x%02x", scancode);
+       //Log_Debug("Keyboard", "scancode = %02x", scancode);
 
        // Ignore ACKs
        if(scancode == 0xFA) {
-               // Oh man! This is anachic (I'm leaving it here to represent the
-               // mess that Acess once was)
+               // Oh man! This is anarchic (I'm leaving it here to represent
+               // the mess that Acess once was)
                //kb_lastChar = KB_ACK;
                return;
        }
@@ -124,7 +126,7 @@ void KB_IRQHandler()
        //keyNum = giKB_KeyLayer * 256 + scancode;
        // Check for unknown key
        if(!ch && !gbKB_KeyUp)
-               Warning("UNK %i %x", giKB_KeyLayer, scancode);
+               Log_Warning("Keyboard", "UNK %i %x", giKB_KeyLayer, scancode);
 
        // Key Up?
        if (gbKB_KeyUp)
@@ -169,8 +171,14 @@ void KB_IRQHandler()
 
        // --- Check for Kernel Magic Combos
        #if USE_KERNEL_MAGIC
-       if(ch == KEY_LCTRL)     gbKB_MagicState |= 1;
-       if(ch == KEY_LALT)      gbKB_MagicState |= 2;
+       if(ch == KEY_LCTRL) {
+               gbKB_MagicState |= 1;
+               //Log_Log("Keyboard", "Kernel Magic LCTRL Down\n");
+       }
+       if(ch == KEY_LALT) {
+               gbKB_MagicState |= 2;
+               //Log_Log("Keyboard", "Kernel Magic LALT Down\n");
+       }
        if(gbKB_MagicState == 3)
        {
                switch(ch)
index 8a86c35..e205d4f 100644 (file)
@@ -4,6 +4,7 @@
  */\r
 #define DEBUG  0\r
 #include <acess.h>\r
+#include <modules.h>\r
 #include <vfs.h>\r
 #include <fs_devfs.h>\r
 #include <drv_pci.h>\r
 #define        LIST_DEVICES    1\r
 \r
 // === STRUCTURES ===\r
-typedef struct s_pciDevice {\r
+typedef struct sPCIDevice\r
+{\r
        Uint16  bus, slot, fcn;\r
        Uint16  vendor, device;\r
        union {\r
-               struct {Uint8 class, subclass;};\r
+               struct {\r
+                       Uint8 class, subclass;\r
+               };\r
                Uint16  oc;\r
        };\r
        Uint16  revision;\r
        Uint32  ConfigCache[256/4];\r
        char    Name[8];\r
        tVFS_Node       Node;\r
-} t_pciDevice;\r
+} tPCIDevice;\r
 \r
 // === CONSTANTS ===\r
 #define SPACE_STEP     5\r
@@ -45,18 +49,18 @@ Uint32      PCI_GetBAR4(int id);
 Uint32 PCI_GetBAR5(int id);\r
 Uint16 PCI_AssignPort(int id, int bar, int count);\r
 \r
- int   PCI_EnumDevice(Uint16 bus, Uint16 dev, Uint16 fcn, t_pciDevice *info);\r
+ int   PCI_EnumDevice(Uint16 bus, Uint16 dev, Uint16 fcn, tPCIDevice *info);\r
 Uint32 PCI_CfgReadDWord(Uint16 bus, Uint16 dev, Uint16 func, Uint16 offset);\r
 void   PCI_CfgWriteDWord(Uint16 bus, Uint16 dev, Uint16 func, Uint16 offset, Uint32 data);\r
 Uint16 PCI_CfgReadWord(Uint16 bus, Uint16 dev, Uint16 func, Uint16 offset);\r
 Uint8  PCI_CfgReadByte(Uint16 bus, Uint16 dev, Uint16 func, Uint16 offset);\r
 \r
 // === GLOBALS ===\r
-//MODULE_DEFINE(0, 0x0100, PCI, PCI_Install, NULL);\r
+MODULE_DEFINE(0, 0x0100, PCI, PCI_Install, NULL, NULL);\r
  int   giPCI_BusCount = 1;\r
  int   giPCI_InodeHandle = -1;\r
  int   giPCI_DeviceCount = 0;\r
-t_pciDevice    *gPCI_Devices = NULL;\r
+tPCIDevice     *gPCI_Devices = NULL;\r
 tDevFS_Driver  gPCI_DriverStruct = {\r
        NULL, "pci",\r
        {\r
@@ -79,7 +83,7 @@ int PCI_Install(char **Arguments)
 {\r
         int    bus, dev, fcn, i;\r
         int    space = 0;\r
-       t_pciDevice     devInfo;\r
+       tPCIDevice      devInfo;\r
        void    *tmpPtr = NULL;\r
        \r
        // Build Portmap\r
@@ -89,25 +93,22 @@ int PCI_Install(char **Arguments)
                gaPCI_PortBitmap[i] = -1;\r
        for( i = 0; i < MAX_RESERVED_PORT % 32; i ++ )\r
                gaPCI_PortBitmap[MAX_RESERVED_PORT / 32] = 1 << i;\r
-       //LogF("Done.\n");\r
        \r
        // Scan Busses\r
        for( bus = 0; bus < giPCI_BusCount; bus++ )\r
        {\r
-               for( dev = 0; dev < 10; dev++ ) // 10 Devices per bus\r
+               for( dev = 0; dev < 32; dev++ ) // 32 Devices per bus\r
                {\r
-                       for( fcn = 0; fcn < 8; fcn++ )  // 8 functions per device\r
+                       for( fcn = 0; fcn < 8; fcn++ )  // Max 8 functions per device\r
                        {\r
                                // Check if the device/function exists\r
                                if(!PCI_EnumDevice(bus, dev, fcn, &devInfo))\r
-                               {\r
                                        continue;\r
-                               }\r
                                \r
                                if(giPCI_DeviceCount == space)\r
                                {\r
                                        space += SPACE_STEP;\r
-                                       tmpPtr = realloc(gPCI_Devices, space*sizeof(t_pciDevice));\r
+                                       tmpPtr = realloc(gPCI_Devices, space*sizeof(tPCIDevice));\r
                                        if(tmpPtr == NULL)\r
                                                break;\r
                                        gPCI_Devices = tmpPtr;\r
@@ -115,20 +116,26 @@ int PCI_Install(char **Arguments)
                                if(devInfo.oc == PCI_OC_PCIBRIDGE)\r
                                {\r
                                        #if LIST_DEVICES\r
-                                       Log("[PCI ] Bridge @ %i,%i:%i (0x%x:0x%x)",\r
+                                       Log_Log("PCI", "Bridge @ %i,%i:%i (0x%x:0x%x)",\r
                                                bus, dev, fcn, devInfo.vendor, devInfo.device);\r
                                        #endif\r
                                        giPCI_BusCount++;\r
                                }\r
+                               else\r
+                               {\r
+                                       #if LIST_DEVICES\r
+                                       Log_Log("PCI", "Device %i,%i:%i %04x => 0x%04x:0x%04x",\r
+                                               bus, dev, fcn, devInfo.oc, devInfo.vendor, devInfo.device);\r
+                                       #endif\r
+                               }\r
+                               \r
                                devInfo.Node.Inode = giPCI_DeviceCount;\r
-                               memcpy(&gPCI_Devices[giPCI_DeviceCount], &devInfo, sizeof(t_pciDevice));\r
+                               memcpy(&gPCI_Devices[giPCI_DeviceCount], &devInfo, sizeof(tPCIDevice));\r
                                giPCI_DeviceCount ++;\r
-                               #if LIST_DEVICES\r
-                               Log("[PCI ] Device %i,%i:%i => 0x%x:0x%x",\r
-                                       bus, dev, fcn, devInfo.vendor, devInfo.device);\r
-                               #endif\r
                                \r
                                // WTF is this for?\r
+                               // Maybe bit 23 must be set for the device to be valid?\r
+                               // - Actually, maybe 23 means that there are sub-functions\r
                                if(fcn == 0) {\r
                                        if( !(devInfo.ConfigCache[3] & 0x800000) )\r
                                                break;\r
@@ -140,19 +147,22 @@ int PCI_Install(char **Arguments)
                if(tmpPtr != gPCI_Devices)\r
                        break;\r
        }\r
-       tmpPtr = realloc(gPCI_Devices, giPCI_DeviceCount*sizeof(t_pciDevice));\r
+       \r
+       if(giPCI_DeviceCount == 0)\r
+               return MODULE_ERR_NOTNEEDED;\r
+       \r
+       tmpPtr = realloc(gPCI_Devices, giPCI_DeviceCount*sizeof(tPCIDevice));\r
        if(tmpPtr == NULL)\r
-               return 0;\r
+               return MODULE_ERR_MALLOC;\r
        gPCI_Devices = tmpPtr;\r
-       //LogF("Done.\n");\r
        \r
-       // Complete Driver Structure    \r
+       // Complete Driver Structure\r
        gPCI_DriverStruct.RootNode.Size = giPCI_DeviceCount;\r
        \r
        // And add to DevFS\r
        DevFS_AddDevice(&gPCI_DriverStruct);\r
        \r
-       return 1;\r
+       return MODULE_ERR_OK;\r
 }\r
 \r
 /**\r
@@ -284,8 +294,8 @@ int PCI_GetDeviceByClass(Uint16 class, Uint16 mask, int prev)
        \r
        for( ; i < giPCI_DeviceCount; i++ )\r
        {\r
-               if((gPCI_Devices[i].oc & mask) != class)        continue;\r
-               return i;\r
+               if((gPCI_Devices[i].oc & mask) == class)\r
+                       return i;\r
        }\r
        return -1;\r
 }\r
@@ -366,7 +376,7 @@ Uint16 PCI_AssignPort(int id, int bar, int count)
        Uint16  portVals;\r
         int    gran=0;\r
         int    i, j;\r
-       t_pciDevice     *dev;\r
+       tPCIDevice      *dev;\r
        \r
        //LogF("PCI_AssignPort: (id=%i,bar=%i,count=%i)\n", id, bar, count);\r
        \r
@@ -423,9 +433,9 @@ Uint16 PCI_AssignPort(int id, int bar, int count)
 }\r
 \r
 /**\r
- * \fn int     PCI_EnumDevice(Uint16 bus, Uint16 slot, Uint16 fcn, t_pciDevice *info)\r
+ * \fn int     PCI_EnumDevice(Uint16 bus, Uint16 slot, Uint16 fcn, tPCIDevice *info)\r
  */\r
-int    PCI_EnumDevice(Uint16 bus, Uint16 slot, Uint16 fcn, t_pciDevice *info)\r
+int    PCI_EnumDevice(Uint16 bus, Uint16 slot, Uint16 fcn, tPCIDevice *info)\r
 {\r
        Uint16  vendor;\r
         int    i;\r
index 52a973c..c007c32 100644 (file)
@@ -68,7 +68,7 @@ tSysFS_Ent    gSysFS_Version = {
                .FindDir = SysFS_Comm_FindDir
        }
 };
-// Root of the SysFS tree (just used for clean code)
+// Root of the SysFS tree (just used to keep the code clean)
 tSysFS_Ent     gSysFS_Root = {
        NULL, NULL,
        NULL,
@@ -77,11 +77,6 @@ tSysFS_Ent   gSysFS_Root = {
                .Size = 1,
                .ImplPtr = &gSysFS_Version,
                .ImplInt = (Uint)&gSysFS_Root   // Self-Link
-       //      .NumACLs = 1,
-       //      .ACLs = &gVFS_ACL_EveryoneRX,
-       //      .Flags = VFS_FFLAG_DIRECTORY,
-       //      .ReadDir = SysFS_Comm_ReadDir,
-       //      .FindDir = SysFS_Comm_FindDir
        }
 };
 tDevFS_Driver  gSysFS_DriverInfo = {
@@ -108,7 +103,7 @@ tSysFS_Ent  *gSysFS_FileList;
 int SysFS_Install(char **Options)
 {
        DevFS_AddDevice( &gSysFS_DriverInfo );
-       return MODULE_INIT_SUCCESS;
+       return MODULE_ERR_OK;
 }
 
 /**
@@ -171,7 +166,7 @@ int SysFS_RegisterFile(char *Path, char *Data, int Length)
                                ent->Node.Size ++;
                        else
                                gSysFS_DriverInfo.RootNode.Size ++;
-                       Log("[SYSFS] Added directory '%s'", child->Name);
+                       Log_Log("SysFS", "Added directory '%s'", child->Name);
                }
                
                ent = child;
@@ -194,7 +189,7 @@ int SysFS_RegisterFile(char *Path, char *Data, int Length)
                        break;
        }
        if( child ) {
-               Warning("[SYSFS] '%s' is taken (in '%s')\n", &Path[start], Path);
+               Log_Warning("SysFS", "'%s' is taken (in '%s')\n", &Path[start], Path);
                return 0;
        }
        
@@ -228,7 +223,7 @@ int SysFS_RegisterFile(char *Path, char *Data, int Length)
        child->ListNext = gSysFS_FileList;
        gSysFS_FileList = child;
        
-       Log("[SYSFS] Added '%s' (%p)", Path, Data);
+       Log_Log("SysFS", "Added '%s' (%p)", Path, Data);
        
        return child->Node.Inode;
 }
@@ -297,7 +292,7 @@ int SysFS_RemoveFile(int ID)
                if( ent == file )       break;
        }
        if(!ent) {
-               Warning("[SYSFS] Bookkeeping Error: File in list, but not in directory");
+               Log_Warning("SysFS", "Bookkeeping Error: File in list, but not in directory");
                return 0;
        }
        
index 11c799c..b0c9662 100644 (file)
@@ -50,7 +50,7 @@ int VGA_Install(char **Arguments)
        // Install DevFS
        DevFS_AddDevice( &gVGA_DevInfo );
        
-       return 1;
+       return MODULE_ERR_OK;
 }
 
 /**
index 7aebd28..cf4efc7 100644 (file)
@@ -21,6 +21,7 @@
 #define VT_SCROLLBACK  1       // 2 Screens of text
 #define DEFAULT_OUTPUT "VGA"
 //#define DEFAULT_OUTPUT       "BochsGA"
+//#define DEFAULT_OUTPUT       "Vesa"
 #define DEFAULT_INPUT  "PS2Keyboard"
 #define        DEFAULT_WIDTH   80
 #define        DEFAULT_HEIGHT  25
@@ -41,13 +42,10 @@ typedef struct {
         int    Flags;  //!< Flags (see VT_FLAG_*)
        short   Width;  //!< Virtual Width
        short   Height; //!< Virtual Height
-       short   RealWidth;      //!< Real Width
-       short   RealHeight;     //!< Real Height
        
         int    ViewPos;        //!< View Buffer Offset (Text Only)
         int    WritePos;       //!< Write Buffer Offset (Text Only)
        Uint32  CurColour;      //!< Current Text Colour
-       char    Name[2];        //!< Name of the terminal
        
         int    InputRead;      //!< Input buffer read position
         int    InputWrite;     //!< Input buffer write position
@@ -56,6 +54,7 @@ typedef struct {
                tVT_Char        *Text;
                Uint32          *Buffer;
        };
+       char    Name[2];        //!< Name of the terminal
        tVFS_Node       Node;
 } tVTerm;
 
@@ -101,6 +100,10 @@ tDevFS_Driver      gVT_DrvInfo = {
 // --- Terminals ---
 tVTerm gVT_Terminals[NUM_VTS];
  int   giVT_CurrentTerminal = 0;
+// --- Video State ---
+short  giVT_RealWidth; //!< Real Width
+short  giVT_RealHeight;        //!< Real Height
+ int   gbVT_TextMode = 1;
 // --- Driver Handles ---
 char   *gsVT_OutputDevice = NULL;
 char   *gsVT_InputDevice = NULL;
@@ -157,8 +160,8 @@ int VT_Install(char **Arguments)
        if(!gsVT_OutputDevice)  gsVT_OutputDevice = "/Devices/"DEFAULT_OUTPUT;
        if(!gsVT_InputDevice)   gsVT_InputDevice = "/Devices/"DEFAULT_INPUT;
        
-       LOG("Using '%s' as output", gsVT_OutputDevice);
-       LOG("Using '%s' as input", gsVT_InputDevice);
+       Log_Log("VTerm", "Using '%s' as output", gsVT_OutputDevice);
+       Log_Log("VTerm", "Using '%s' as input", gsVT_InputDevice);
        
        // Create Nodes
        for( i = 0; i < NUM_VTS; i++ )
@@ -190,7 +193,7 @@ int VT_Install(char **Arguments)
        // Set kernel output to VT0
        Debug_SetKTerminal("/Devices/VTerm/0");
        
-       return MODULE_INIT_SUCCESS;
+       return MODULE_ERR_OK;
 }
 
 /**
@@ -349,7 +352,7 @@ Uint64 VT_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
                VT_int_PutString(term, Buffer, Length);
                break;
        case TERM_MODE_FB:
-               if( term->RealWidth > term->Width || term->RealHeight > term->Height )
+               if( giVT_RealWidth > term->Width || giVT_RealHeight > term->Height )
                {
                        #if 0
                         int    x, y, h;
@@ -443,38 +446,41 @@ int VT_Terminal_IOCtl(tVFS_Node *Node, int Id, void *Data)
        return -1;
 }
 
-/**
- * \fn void VT_SetTerminal(int ID)
- * \brief Set the current terminal
- */
-void VT_SetTerminal(int ID)
+void VT_SetResolution(int IsTextMode, int Width, int Height)
 {
        tVideo_IOCtl_Mode       mode = {0};
-        int    modeNum;
+        int    tmp;
        
        // Create the video mode
-       mode.width = gVT_Terminals[ ID ].Width;
-       mode.height = gVT_Terminals[ ID ].Height;
-       // - Text Mode
-       if(gVT_Terminals[ ID ].Mode == TERM_MODE_TEXT) {
-               mode.bpp = 12;
-               mode.flags = VIDEO_FLAG_TEXT;
-       }
-       // - Framebuffer or 3D
-       else {
-               mode.bpp = 32;
-               mode.flags = 0;
-       }
+       mode.width = Width;
+       mode.height = Height;
+       mode.bpp = 32;
+       mode.flags = 0;
        
        // Set video mode
        VFS_IOCtl( giVT_OutputDevHandle, VIDEO_IOCTL_FINDMODE, &mode );
-       modeNum = mode.id;
-       gVT_Terminals[ ID ].RealWidth = mode.width;
-       gVT_Terminals[ ID ].RealHeight = mode.height;
-       VFS_IOCtl( giVT_OutputDevHandle, VIDEO_IOCTL_GETSETMODE, &modeNum );
+       tmp = mode.id;
+       giVT_RealWidth = mode.width;
+       giVT_RealHeight = mode.height;
+       VFS_IOCtl( giVT_OutputDevHandle, VIDEO_IOCTL_GETSETMODE, &tmp );
+       
+       
        
+       if(IsTextMode)
+               tmp = VIDEO_BUFFMT_TEXT;
+       else
+               tmp = VIDEO_BUFFMT_FRAMEBUFFER;
+       VFS_IOCtl( giVT_OutputDevHandle, VIDEO_IOCTL_SETBUFFORMAT, &tmp );
+}
+
+/**
+ * \fn void VT_SetTerminal(int ID)
+ * \brief Set the current terminal
+ */
+void VT_SetTerminal(int ID)
+{      
        // Update current terminal ID
-       Log("Changed terminal from %i to %i", giVT_CurrentTerminal, ID);
+       Log_Log("VTerm", "Changed terminal from %i to %i", giVT_CurrentTerminal, ID);
        giVT_CurrentTerminal = ID;
        
        // Update the screen
@@ -914,21 +920,41 @@ void VT_int_UpdateScreen( tVTerm *Term, int UpdateAll )
        
        if( Term->Mode == TERM_MODE_TEXT )
        {
-               if(UpdateAll) {
-                       VFS_WriteAt(
-                               giVT_OutputDevHandle,
-                               0,
-                               Term->Width*Term->Height*sizeof(tVT_Char),
-                               &Term->Text[Term->ViewPos]
-                               );
-               } else {
-                        int    pos = Term->WritePos - Term->WritePos % Term->Width;
-                       VFS_WriteAt(
-                               giVT_OutputDevHandle,
-                               (pos - Term->ViewPos)*sizeof(tVT_Char),
-                               Term->Width*sizeof(tVT_Char),
-                               &Term->Text[pos]
-                               );
+               if(gbVT_TextMode)
+               {
+                       if(UpdateAll) {
+                               VFS_WriteAt(
+                                       giVT_OutputDevHandle,
+                                       0,
+                                       Term->Width*Term->Height*sizeof(tVT_Char),
+                                       &Term->Text[Term->ViewPos]
+                                       );
+                       } else {
+                                int    pos = Term->WritePos - Term->WritePos % Term->Width;
+                               VFS_WriteAt(
+                                       giVT_OutputDevHandle,
+                                       (pos - Term->ViewPos)*sizeof(tVT_Char),
+                                       Term->Width*sizeof(tVT_Char),
+                                       &Term->Text[pos]
+                                       );
+                       }
+               }
+               else
+               {
+                       //TODO: Do VT Rendered Text
+                       #if 0
+                       if( UpdateAll ) {
+                               VT_RenderText(0, Term->Width*Term->Height, &Term->Text[Term->ViewPos]);
+                       }
+                       else {
+                                int    pos = Term->WritePos - Term->WritePos % Term->Width;
+                               VT_RenderText(
+                                       pos - Term->ViewPos,
+                                       Term->Width,
+                                       &Term->Text[pos]
+                                       );
+                       }
+                       #endif
                }
        }
        else
index 61f7881..9d282b9 100644 (file)
@@ -151,7 +151,7 @@ void *malloc(size_t Bytes)
                // Alignment Check
                if( head->Size & (BLOCK_SIZE-1) ) {
                        #if WARNINGS
-                       Warning("Size of heap address %p is invalid not aligned (0x%x)", head, head->Size);
+                       Log_Warning("Heap", "Size of heap address %p is invalid not aligned (0x%x)", head, head->Size);
                        Heap_Dump();
                        #endif
                        RELEASE(&glHeap);
@@ -163,7 +163,7 @@ void *malloc(size_t Bytes)
                // Error check
                if(head->Magic != MAGIC_FREE)   {
                        #if WARNINGS
-                       Warning("Magic of heap address %p is invalid (0x%x)", head, head->Magic);
+                       Log_Warning("Heap", "Magic of heap address %p is invalid (0x%x)", head, head->Magic);
                        Heap_Dump();
                        #endif
                        RELEASE(&glHeap);       // Release spinlock
@@ -178,9 +178,9 @@ void *malloc(size_t Bytes)
                        head->Magic = MAGIC_USED;
                        RELEASE(&glHeap);       // Release spinlock
                        #if DEBUG_TRACE
-                       LOG("RETURN %p, to %p", best->Data, __builtin_return_address(0));
+                       Log("[Heap   ] Malloc'd %p (%i bytes), returning to %p", head->Data, head->Size,  __builtin_return_address(0));
                        #endif
-                       return best->Data;
+                       return head->Data;
                }
                
                // Break out of loop
@@ -210,7 +210,7 @@ void *malloc(size_t Bytes)
                if(best->Size == Bytes) {
                        RELEASE(&glHeap);       // Release spinlock
                        #if DEBUG_TRACE
-                       LOG("RETURN %p, to %p", best->Data, __builtin_return_address(0));
+                       Log("[Heap   ] Malloc'd %p (%i bytes), returning to %p", best->Data, best->Size, __builtin_return_address(0));
                        #endif
                        return best->Data;
                }
@@ -231,7 +231,7 @@ void *malloc(size_t Bytes)
        
        RELEASE(&glHeap);       // Release spinlock
        #if DEBUG_TRACE
-       LOG("RETURN %p, to %p", best->Data, __builtin_return_address(0));
+       Log("[Heap   ] Malloc'd %p (%i bytes), returning to %p", best->Data, best->Size, __builtin_return_address(0));
        #endif
        return best->Data;
 }
@@ -246,42 +246,43 @@ void free(void *Ptr)
        tHeapFoot       *foot;
        
        #if DEBUG_TRACE
-       LOG("Ptr = %p", Ptr);
-       LOG("Returns to %p", __builtin_return_address(0));
+       Log_Log("Heap", "free: Ptr = %p", Ptr);
+       Log_Log("Heap", "free: Returns to %p", __builtin_return_address(0));
        #endif
        
        // Alignment Check
        if( (Uint)Ptr & (sizeof(Uint)-1) ) {
-               Warning("free - Passed a non-aligned address (%p)", Ptr);
+               Log_Warning("Heap", "free - Passed a non-aligned address (%p)", Ptr);
                return;
        }
        
        // Sanity check
        if((Uint)Ptr < (Uint)gHeapStart || (Uint)Ptr > (Uint)gHeapEnd)
        {
-               Warning("free - Passed a non-heap address (%p)\n", Ptr);
+               Log_Warning("Heap", "free - Passed a non-heap address (%p < %p < %p)\n",
+                       gHeapStart, Ptr, gHeapEnd);
                return;
        }
        
        // Check memory block - Header
        head = (void*)( (Uint)Ptr - sizeof(tHeapHead) );
        if(head->Magic == MAGIC_FREE) {
-               Warning("free - Passed a freed block (%p) by %p", head, __builtin_return_address(0));
+               Log_Warning("Heap", "free - Passed a freed block (%p) by %p", head, __builtin_return_address(0));
                return;
        }
        if(head->Magic != MAGIC_USED) {
-               Warning("free - Magic value is invalid (%p, 0x%x)\n", head, head->Magic);
+               Log_Warning("Heap", "free - Magic value is invalid (%p, 0x%x)\n", head, head->Magic);
                return;
        }
        
        // Check memory block - Footer
        foot = (void*)( (Uint)head + head->Size - sizeof(tHeapFoot) );
        if(foot->Head != head) {
-               Warning("free - Footer backlink is incorrect (%p, 0x%x)\n", head, foot->Head);
+               Log_Warning("Heap", "free - Footer backlink is incorrect (%p, 0x%x)\n", head, foot->Head);
                return;
        }
        if(foot->Magic != MAGIC_FOOT) {
-               Warning("free - Footer magic is invalid (%p, %p = 0x%x)\n", head, &foot->Magic, foot->Magic);
+               Log_Warning("Heap", "free - Footer magic is invalid (%p, %p = 0x%x)\n", head, &foot->Magic, foot->Magic);
                return;
        }
        
@@ -387,13 +388,14 @@ void *calloc(size_t num, size_t size)
 
 /**
  * \fn int IsHeap(void *Ptr)
- * \brief Checks if an address is a heap address
+ * \brief Checks if an address is a heap pointer
  */
 int IsHeap(void *Ptr)
 {
        tHeapHead       *head;
        if((Uint)Ptr < (Uint)gHeapStart)        return 0;
        if((Uint)Ptr > (Uint)gHeapEnd)  return 0;
+       if((Uint)Ptr & (sizeof(Uint)-1))        return 0;
        
        head = (void*)( (Uint)Ptr - sizeof(tHeapHead) );
        if(head->Magic != MAGIC_USED && head->Magic != MAGIC_FREE)
@@ -412,31 +414,31 @@ void Heap_Dump()
        while( (Uint)head < (Uint)gHeapEnd )
        {               
                foot = (void*)( (Uint)head + head->Size - sizeof(tHeapFoot) );
-               Log("%p (0x%x): 0x%08lx 0x%lx", head, MM_GetPhysAddr((Uint)head), head->Size, head->Magic);
-               Log("%p 0x%lx", foot->Head, foot->Magic);
-               Log("");
+               Log_Log("Heap", "%p (0x%x): 0x%08lx 0x%lx", head, MM_GetPhysAddr((Uint)head), head->Size, head->Magic);
+               Log_Log("Heap", "%p 0x%lx", foot->Head, foot->Magic);
+               Log_Log("Heap", "");
                
                // Sanity Check Header
                if(head->Size == 0) {
-                       Log("HALTED - Size is zero");
+                       Log_Warning("Heap", "HALTED - Size is zero");
                        break;
                }
                if(head->Size & (BLOCK_SIZE-1)) {
-                       Log("HALTED - Size is malaligned");
+                       Log_Warning("Heap", "HALTED - Size is malaligned");
                        break;
                }
                if(head->Magic != MAGIC_FREE && head->Magic != MAGIC_USED) {
-                       Log("HALTED - Head Magic is Bad");
+                       Log_Warning("Heap", "HALTED - Head Magic is Bad");
                        break;
                }
                
                // Check footer
                if(foot->Magic != MAGIC_FOOT) {
-                       Log("HALTED - Foot Magic is Bad");
+                       Log_Warning("Heap", "HALTED - Foot Magic is Bad");
                        break;
                }
                if(head != foot->Head) {
-                       Log("HALTED - Footer backlink is invalid");
+                       Log_Warning("Heap", "HALTED - Footer backlink is invalid");
                        break;
                }
                
index 2cd927b..963cb9c 100644 (file)
@@ -8,6 +8,7 @@
 #define NULL   ((void*)0)
 #define PACKED __attribute__ ((packed))
 
+#include <stdint.h>
 #include <arch.h>
 #include <stdarg.h>
 #include "errno.h"
@@ -100,6 +101,15 @@ extern void        System_Init(char *ArgString);
 // --- IRQs ---
 extern int     IRQ_AddHandler(int Num, void (*Callback)(int));
 
+// --- Logging ---
+extern void    Log_KernelPanic(char *Ident, char *Message, ...);
+extern void    Log_Panic(char *Ident, char *Message, ...);
+extern void    Log_Error(char *Ident, char *Message, ...);
+extern void    Log_Warning(char *Ident, char *Message, ...);
+extern void    Log_Notice(char *Ident, char *Message, ...);
+extern void    Log_Log(char *Ident, char *Message, ...);
+extern void    Log_Debug(char *Ident, char *Message, ...);
+
 // --- Debug ---
 /**
  * \name Debugging and Errors
@@ -214,7 +224,7 @@ extern void MM_FreeTemp(tVAddr VAddr);
  * \param PAddr        Physical address to map in
  * \param Number       Number of pages to map
  */
-extern tVAddr  MM_MapHWPage(tPAddr PAddr, Uint Number);
+extern tVAddr  MM_MapHWPages(tPAddr PAddr, Uint Number);
 /**
  * \brief Allocates DMA physical memory
  * \param Pages        Number of pages required
@@ -228,7 +238,7 @@ extern tVAddr       MM_AllocDMA(int Pages, int MaxBits, tPAddr *PhysAddr);
  * \param VAddr        Virtual address allocate by ::MM_MapHWPage or ::MM_AllocDMA
  * \param Number       Number of pages to free
  */
-extern void    MM_UnmapHWPage(tVAddr VAddr, Uint Number);
+extern void    MM_UnmapHWPages(tVAddr VAddr, Uint Number);
 /**
  * \brief Allocate a single physical page
  * \return Physical address allocated
@@ -295,9 +305,11 @@ extern Uint32      BigEndian32(Uint32 Val);
  * \name Strings
  * \{
  */
+extern int     vsnprintf(char *__s, size_t __maxlen, const char *__format, va_list args);
 extern int     sprintf(char *__s, const char *__format, ...);
 extern Uint    strlen(const char *Str);
 extern char    *strcpy(char *__dest, const char *__src);
+extern char    *strncpy(char *__dest, const char *__src, size_t max);
 extern int     strcmp(const char *__str1, const char *__str2);
 extern int     strncmp(const char *Str1, const char *Str2, size_t num);
 extern int     strucmp(const char *Str1, const char *Str2);
@@ -316,6 +328,7 @@ extern Uint8        ByteSum(void *Ptr, int Size);
  */
 
 extern Uint    rand();
+extern int     CallWithArgArray(void *Function, int NArgs, Uint *Args);
 
 // --- Heap ---
 /**
@@ -369,12 +382,14 @@ extern int        Proc_Spawn(char *Path);
 extern void    Threads_Exit();
 extern void    Threads_Yield();
 extern void    Threads_Sleep();
+extern void    Threads_WakeTID(tTID Thread);
 extern tPID    Threads_GetPID();
 extern tTID    Threads_GetTID();
 extern tUID    Threads_GetUID();
 extern tGID    Threads_GetGID();
 extern int     SpawnTask(tThreadFunction Function, void *Arg);
 extern Uint    *Threads_GetCfgPtr(int Id);
+extern int     Threads_SetName(char *NewName);
 /**
  * \}
  */
diff --git a/Kernel/include/apidoc/arch_x86.h b/Kernel/include/apidoc/arch_x86.h
new file mode 100644 (file)
index 0000000..7818c8c
--- /dev/null
@@ -0,0 +1,38 @@
+/**
+ * \file apidoc/arch_x86.h
+ * \brief x86(-64) Specific Functions
+ * \author John Hodge (thePowersGang)
+ *
+ * \section toc        Table of Contents
+ * - \ref portio "Port IO"
+ * - \ref dma "DMA - Direct Memory Access"
+ * 
+ * \section portio Port IO
+ * The x86 architecture has two memory spaces, the first is the system
+ * memory accessable using standard loads and stores. The second is the
+ * 16-bit IO Bus. This bus is accessed using the \a in and \a out opcodes
+ * and is used to configure devices attached to the system.
+ * A driver should not use \a in and \a out directly, but instead use
+ * the provided \a in* and \a out* functions to access the IO Bus.
+ * This allows the kernel to run a driver in userspace if requested without
+ * the binary needing to be altered.
+ * 
+ * \section dma        DMA - Direct Memory Access
+ */
+
+/**
+ * \name IO Bus Access
+ * \{
+ */
+extern Uint8   inb(Uint16 Port);       //!< Read 1 byte from the IO Bus
+extern Uint16  inw(Uint16 Port);       //!< Read 2 bytes from the IO Bus
+extern Uint32  inl(Uint16 Port);       //!< Read 4 bytes from the IO Bus
+extern Uint64  inq(Uint16 Port);       //!< Read 8 bytes from the IO Bus\
+
+extern void    outb(Uint16 Port, Uint8 Value); //!< Write 1 byte to the IO Bus
+extern void    outw(Uint16 Port, Uint16 Value);        //!< Write 2 bytes to the IO Bus
+extern void    outl(Uint16 Port, Uint32 Value);        //!< Write 4 bytes to the IO Bus
+extern void    outq(Uint16 Port, Uint64 Value);        //!< Write 8 bytes to the IO Bus
+/**
+ * \}
+ */
index 98a5e40..29a6c00 100644 (file)
  * 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
+ * \section index      "Sections"
+ * - \ref modules.h "Module Definitions"
+ *  - Describes how a module is defined in Acess
+ * - \ref binary.h     "Binary Formats"
+ *  - Explains how to register a new binary format with the kernel
+ * - \ref vfs.h        "VFS - The Virtual File System"
+ *  - The VFS is the core of Acess's driver architecture
+ * - \ref drivers      "Device Drivers"
+ *  - Describes how drivers should use the VFS to expose themselves to the
+ *    user.
+ *  - Drivers for specific types of hardware must behave in the specific
+ *    way described here.
+ * 
+ * \page drivers Device Drivers
+ * 
+ * \section toc        Contents
+ * - \ref drvintro     "Introduction"
+ * - \ref drv_misc "Miscelanious Devices"
+ * - \ref drv_video    "Video Drivers"
+ * 
+ * \section drvintro   Introduction
  * 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)
+ * \ref fs_devfs.h "Device Filesystem" (devfs). The DevFS provides the
+ * ::DevFS_AddDevice function that takes a ::tDevFS_Driver structure as
+ * an agument. This structure specifies the driver's name and its root
+ * VFS node. This node is used to provide the user access to the
+ * driver's functions via IOCtl calls and Reading or Writing to the driver
+ * file. Drivers are also able to expose a readonly buffer by using
+ * \ref fs_proc.h ProcDev, usually to provide state information or device
+ * capabilities for the the user.
  * 
  * The device driver interfaces are all based on the core specifcation
  * in tpl_drv_common.h (Common Device Driver definitions).
  * IOCtl calls and/or files (where allowed by the type specifcation) to
  * their device's VFS layout.
  * 
+ * \subsection drv_misc Miscelanious Devices
+ * If a device type does not have a specifcation for it, the driver can
+ * identify itself as a miscelanious device by returning DRV_TYPE_MISC
+ * from \ref DRV_IOCTL_TYPE.
+ * A misc device must at least implement the IOCtl calls defined in the
+ * \ref tpl_drv_common.h "Common Device Driver definitions", allowing it
+ * to be identified easily by the user and for interfacing programs to
+ * utilise the DRV_IOCTL_LOOKUP call.
+ * 
  * \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).
index 5b0bbda..b1a6d1a 100644 (file)
@@ -6,5 +6,6 @@
 
 extern void    DMA_SetChannel(int channel, int length, int read);
 extern int     DMA_ReadData(int channel, int count, void *buffer);
+extern int     DMA_WriteData(int channel, int count, void *buffer);
 
 #endif
index b539430..d3eb8a2 100644 (file)
@@ -1,12 +1,16 @@
-/*\r
- * Acess 2\r
- * PCI Bus Driver\r
- * drv_pci.h\r
+/**\r
+ * \file drv_pci.h\r
+ * \brief PCI Bus Driver\r
+ * \author John Hodge (thePowersGang)\r
  */\r
 #ifndef _DRV_PCI_H\r
 #define _DRV_PCI_H\r
 \r
-enum e_PciClasses {\r
+/**\r
+ * \brief PCI Class Codes\r
+ */\r
+enum ePCIClasses\r
+{\r
        PCI_CLASS_PRE20 = 0x00,\r
        PCI_CLASS_STORAGE,\r
        PCI_CLASS_NETWORK,\r
@@ -22,13 +26,20 @@ enum e_PciClasses {
        PCI_CLASS_SERIALBUS,\r
        PCI_CLASS_MISC = 0xFF\r
 };\r
-enum e_PciOverClasses {\r
+\r
+enum ePCIOverClasses\r
+{\r
        PCI_OC_PCIBRIDGE = 0x0604,\r
        PCI_OC_SCSI = 0x0100\r
 };\r
 \r
-\r
+/**\r
+ * \brief Count PCI Devices\r
+ * \r
+ * Counts the number of devices with specified Vendor and Device IDs\r
+ */\r
 extern int     PCI_CountDevices(Uint16 vendor, Uint16 device, Uint16 fcn);\r
+\r
 extern int     PCI_GetDevice(Uint16 vendor, Uint16 device, Uint16 fcn, int idx);\r
 extern int     PCI_GetDeviceByClass(Uint16 class, Uint16 mask, int prev);\r
 extern Uint8   PCI_GetIRQ(int id);\r
index 8bf83d8..0b796c0 100644 (file)
@@ -1,16 +1,20 @@
 /*
- * AcessOS Microkernel Version
+ * Acess2
  * errno.h
  */
 #ifndef _ERRNO_H
 #define _ERRNO_H
 
-enum eErrorNums {
+enum eErrorNums
+{
        EOK,
        ENOSYS,
        EINVAL,
        ENOMEM,
-       EACCES
+       EACCES,
+       ENOTFOUND,
+       EREADONLY,
+       ENOTIMPL
 };
 
 #endif
index 54f4280..f75a7ff 100644 (file)
@@ -21,10 +21,15 @@ typedef struct sDevFS_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
+ * \brief Registers a device in the Device Filesystem
+ * \param Device       Pointer to a persistant structure that represents the driver
  * \return Boolean success
  */
-extern int     DevFS_AddDevice(tDevFS_Driver *Dev);
+extern int     DevFS_AddDevice(tDevFS_Driver *Device);
+
+/**
+ * \brief Unregisters a device with the Device Filesystem
+ */
+extern void    DevFS_DelDevice(tDevFS_Driver *Device);
 
 #endif
index ff59d54..6d5e6a4 100644 (file)
@@ -5,6 +5,8 @@
 #ifndef _MBOOT_H
 #define _MBOOT_H
 
+#define MULTIBOOT_MAGIC        0x2BADB002
+
 // === TYPES ===
 typedef struct {
        Uint32  Flags;
index d53f774..8862112 100644 (file)
@@ -2,11 +2,36 @@
  * AcessOS 2
  * - Module Loader
  */
+/**
+ * \file modules.h
+ * \brief Module Handling and Loader Definitions
+ * \author John Hodge (thePowersGang)
+ * 
+ * This file serves two pourposes. First it defines the format for native
+ * Acess2 modules and the functions to create them.
+ * Second, it defines the structure and register function for new module
+ * loaders, allowing Acess to understand many different module / driver
+ * formats.
+ * 
+ * Modules are defined by including this file in the module's main source
+ * file and using the ::MODULE_DEFINE macro to create the module header.
+ * 
+ * To register a new module loader with the kernel, the loader module must
+ * create and populate an instance of ::tModuleLoader then pass it to
+ * ::Module_RegisterLoader
+ */
 #ifndef _MODULE_H
 #define _MODULE_H
 
+/**
+ * \brief Module header magic value
+ */
 #define MODULE_MAGIC   ('A'|('M'<<8)|('D'<<16)|('\2'<<24))
 
+/**
+ * \def MODULE_ARCH_ID
+ * \brief Architecture ID
+ */
 // IA32 - Architecture 1
 #if ARCHDIR == x86
 # define MODULE_ARCH_ID        1
 # error "Unknown architecture when determining MODULE_ARCH_ID ('" #ARCHDIR "')"
 #endif
 
+/**
+ * \brief Define a module
+ * \param _flags       Module Flags
+ * \param _ver Module Version
+ * \param _ident       Unique Module Name
+ * \param _entry       Module initialiser / entrypoint
+ * \param _deinit      Module cleanup / unloader
+ * \param _deps        NULL terminated list of this's module's dependencies
+ *                     Contains the identifiers of the required modules.
+ */
 #define MODULE_DEFINE(_flags,_ver,_ident,_entry,_deinit,_deps...) \
        char *EXPAND_CONCAT(_DriverDeps_,_ident)[]={_deps};\
        tModule __attribute__ ((section ("KMODULES"),unused))\
        {MODULE_MAGIC,MODULE_ARCH_ID,_flags,_ver,NULL,EXPAND_STR(_ident),\
        _entry,_deinit,EXPAND_CONCAT(_DriverDeps_,_ident)}
 
-typedef struct sModule {
-       Uint32  Magic;
-       Uint8   Arch;
-       Uint8   Flags;
-       Uint16  Version;
-       struct sModule  *Next;
-       char    *Name;
-        int    (*Init)(char **Arguments);
-       void    (*Deinit)();
-       char    **Dependencies; // NULL Terminated List
-} __attribute__((packed)) tModule;
+/**
+ * \brief Module header
+ * \note There is no reason for a module to touch this structure beyond
+ *       using ::MODULE_DEFINE to create it.
+ */
+typedef struct sModule 
+{
+       Uint32  Magic;  //!< Identifying magic value (See ::MODULE_MAGIC)
+       Uint8   Arch;   //!< Achitecture ID (See ::MODULE_ARCH_ID)
+       Uint8   Flags;  //!< Module Flags
+       Uint16  Version;        //!< Module Version in Major.Minor 8.8 form
+       struct sModule  *Next;  //!< Next module in list (not to be touched by the driver)
+       char    *Name;  //!< Module Name/Identifier
+        int    (*Init)(char **Arguments);      //!< Module initialiser / entrypoint
+       void    (*Deinit)();    //!< Cleanup Function
+       char    **Dependencies; //!< NULL terminated list of dependencies
+} PACKED tModule;
 
-#define MODULE_INIT_SUCCESS    1
-#define MODULE_INIT_FAILURE    0
+/**
+ * \brief Return values for tModule.Init
+ */
+enum eModuleErrors
+{
+       MODULE_ERR_OK,  //!< No Error
+       MODULE_ERR_MISC,        //!< Misc Error
+       MODULE_ERR_NOTNEEDED,   //!< Module not needed
+       MODULE_ERR_MALLOC,      //!< Error with malloc/realloc/calloc
+       
+       MODULE_ERR_MAX  //!< Maximum defined error code
+};
 
 /**
  * \brief Module Loader definition
@@ -45,7 +96,8 @@ typedef struct sModule {
  * Allows a module to extend the loader to recognise other module types
  * E.g. EDI, UDI, Windows, Linux, ...
  */
-typedef struct sModuleLoader {
+typedef struct sModuleLoader
+{
        struct sModuleLoader    *Next;  //!< Kernel Only - Next loader in list
        char    *Name;  //!< Friendly name for the loader
         int    (*Detector)(void *Base);        //!< Simple detector function
@@ -56,6 +108,7 @@ typedef struct sModuleLoader {
 /**
  * \brief Registers a tModuleLoader with the kernel
  * \param Loader       Pointer to loader structure (must be persistent)
+ * \return Boolean Success
  */
 extern int     Module_RegisterLoader(tModuleLoader *Loader);
 
index 9c5ebe7..b55fe0e 100644 (file)
@@ -19,7 +19,7 @@ typedef struct sThread
        // --- threads.c's
        struct sThread  *Next;  //!< Next thread in list
        tSpinlock       IsLocked;       //!< Thread's spinlock
-        int    Status;         //!< Thread Status
+       volatile int    Status;         //!< Thread Status
         int    RetStatus;      //!< Return Status
        
        Uint    TID;    //!< Thread ID
index bf3d286..ebbe98f 100644 (file)
  * but they may choose not to allow direct user access to the framebuffer.\r
  * \r
  * \section Screen Contents\r
- * Reads and writes to the driver's file while in component colour modes\r
+ * Writes to the driver's file while in component colour modes\r
  * must correspond to a change of the contents of the screen. The framebuffer\r
  * must start at offset 0 in the file.\r
  * In pallete colour modes the LFB is preceded by a 1024 byte pallete (allowing\r
  * room for 256 entries of 32-bits each)\r
-*/\r
+ * Reading from the screen must either return zero, or read from the\r
+ * framebuffer.\r
+ * \r
+ * \section Mode Support\r
+ * All video drivers must support at least one text mode (Mode #0)\r
+ * For each graphics mode the driver exposes, there must be a corresponding\r
+ * text mode with the same resolution, this mode will be used when the\r
+ * user switches to a text Virtual Terminal while in graphics mode.\r
+ */\r
 #ifndef _TPL_VIDEO_H\r
 #define _TPL_VIDEO_H\r
 \r
@@ -59,6 +67,17 @@ enum eTplVideo_IOCtl {
         */\r
        VIDEO_IOCTL_MODEINFO,\r
        \r
+       /**\r
+        * ioctl(..., int *NewFormat)\r
+        * \brief Switches between Text, Framebuffer and 3D modes\r
+        * \param NewFormat     Pointer to the new format code (see eTplVideo_BufFormats)\r
+        * \return Original format\r
+        * \r
+        * Enabes and disables the video text mode, changing the behavior of\r
+        * writes to the device file.\r
+        */\r
+       VIDEO_IOCTL_SETBUFFORMAT,\r
+       \r
        /**\r
         * ioctl(..., tVideo_IOCtl_Pos *pos)\r
         * \brief Sets the cursor position\r
@@ -101,18 +120,15 @@ typedef struct sVideo_IOCtl_Mode
        Uint8   flags;  //!< Mode Flags\r
 }      tVideo_IOCtl_Mode;\r
 \r
-//! \name Video Mode flags\r
-//! \{\r
-/**\r
- * \brief Text Mode Flag\r
- * \note A text mode should have the ::sVideo_IOCtl_Mode.bpp set to 12\r
- */\r
-#define VIDEO_FLAG_TEXT        0x1\r
 /**\r
- * \brief Slow (non-accellerated mode)\r
+ * \brief Buffer Format Codes\r
  */\r
-#define VIDEO_FLAG_SLOW        0x2\r
-//! \}\r
+enum eTplVideo_BufFormats\r
+{\r
+       VIDEO_BUFFMT_TEXT,\r
+       VIDEO_BUFFMT_FRAMEBUFFER,\r
+       VIDEO_BUFFMT_3DSTREAM\r
+};\r
 \r
 /**\r
  * \brief Describes a position in the video framebuffer\r
index 337d8e7..e3a61d4 100644 (file)
@@ -5,6 +5,16 @@
 /**
  * \file vfs.h
  * \brief Acess VFS Layer
+ * 
+ * The Acess Virtual File System (VFS) provides abstraction of multiple
+ * physical filesystems, network storage and devices (both hardware and
+ * virtual) to the user.
+ * 
+ * The core of the VFS is the concept of a \ref tVFS_Node "VFS Node".
+ * A VFS Node represents a "file" in the VFS tree, this can be any sort
+ * of file (an ordinary file, a directory, a symbolic link or a device)
+ * depending on the bits set in the \ref tVFS_Node.Flags Flags field.
+ * - For more information see "VFS Node Flags"
  */
 #ifndef _VFS_H
 #define _VFS_H
 #include <acess.h>
 
 /**
- * \name VFS Node Flags
+ * \name tVFS_Node Flags
+ * \brief Flag values for tVFS_Node.Flags
  * \{
  */
-#define VFS_FFLAG_READONLY     0x01    //!< Read-only file
-#define VFS_FFLAG_DIRECTORY    0x02    //!< Directory
-#define VFS_FFLAG_SYMLINK      0x04    //!< Symbolic Link
+//! \todo Is this still needed
+#define VFS_FFLAG_READONLY     0x01    //!< Readonly File
+/**
+ * \brief Directory Flag
+ * 
+ * This flag marks the tVFS_Node as describing a directory, and says
+ * that the tVFS_Node.FindDir, tVFS_Node.ReadDir, tVFS_Node.MkNod and
+ * tVFS_Node.Relink function pointers are valid.
+ * For a directory the tVFS_Node.Size field contains the number of files
+ * within the directory, or -1 for undetermined.
+ */
+#define VFS_FFLAG_DIRECTORY    0x02
+/**
+ * \brief Symbolic Link Flag
+ * 
+ * Marks a file as a symbolic link
+ */
+#define VFS_FFLAG_SYMLINK      0x04
+/**
+ * \brief Set User ID Flag
+ * 
+ * Allows an executable file to change it's executing user to the file's
+ * owner.
+ * In the case of a directory, it means that all immediate children will
+ * inherit the UID of the parent.
+ */
+#define VFS_FFLAG_SETUID       0x08
+/**
+ * \brief Set Group ID Flag
+ * 
+ * Allows an executable file to change it's executing group to the file's
+ * owning group.
+ * In the case of a directory, it means that all immediate children will
+ * inherit the GID of the parent.
+ */
+#define VFS_FFLAG_SETGID       0x10
 /**
  * \}
  */
 
 /**
  * \brief VFS Node
- * \todo Complete / Finalise
+ * 
+ * This structure provides the VFS with the functions required to read/write
+ * the file (or directory) that it represents.
  */
-typedef struct sVFS_Node {     
-       Uint64  Inode;  //!< Inode ID
+typedef struct sVFS_Node
+{
+       /**
+        * \name Identifiers
+        * \brief Fields used by the driver to identify what data this node
+        *        corresponds to.
+        * \{
+        */
+       Uint64  Inode;  //!< Inode ID (Essentially another ImplInt)
        Uint    ImplInt;        //!< Implementation Usable Integer
        void    *ImplPtr;       //!< Implementation Usable Pointer
+       /**
+        * \}
+        */
        
+       /**
+        * \name Node State
+        * \brief Stores the misc information about the node
+        * \{
+        */
         int    ReferenceCount; //!< Number of times the node is used
        
        Uint64  Size;   //!< File Size
        
        Uint32  Flags;  //!< File Flags
        
+       /**
+        * Pointer to cached data (FS Specific)
+        * \note Inode_* will free when the node is uncached this if needed
+        */
+       void    *Data;
+       /**
+        * \}
+        */
+       
+       /**
+        * \name Times
+        * \{
+        */
        Sint64  ATime;  //!< Last Accessed Time
        Sint64  MTime;  //!< Last Modified Time
        Sint64  CTime;  //!< Creation Time
+       /**
+        * \}
+        */
        
-       Uint    UID;    //!< Owning User
-       Uint    GID;    //!< Owning Group
+       /**
+        * \name Access controll
+        * \{
+        */
+       tUID    UID;    //!< ID of Owning User
+       tGID    GID;    //!< ID of Owning Group
        
         int    NumACLs;        //!< Number of ACL entries
-       tVFS_ACL        *ACLs;  //!< ACL Entries
+       tVFS_ACL        *ACLs;  //!< Access Controll List pointer
+       /**
+        * \}
+        */
        
+       /**
+        * \name Common Functions
+        * \brief Functions that are used no matter the value of .Flags
+        * \{
+        */
        /**
         * \brief Reference the node
         * \param Node Pointer to this node
@@ -70,6 +159,17 @@ typedef struct sVFS_Node {
         */
         int    (*IOCtl)(struct sVFS_Node *Node, int Id, void *Data);
        
+       /**
+        * }
+        */
+       
+       /**
+        * \name Buffer Functions
+        * \brief Functions for accessing a buffer-type file (normal file or
+        *        symbolic link)
+        * \{
+        */
+       
        /**
         * \brief Read from the file
         * \param Node  Pointer to this node
@@ -89,6 +189,14 @@ typedef struct sVFS_Node {
         */
        Uint64  (*Write)(struct sVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
        
+       /**
+        * }
+        */
+       
+       /**
+        * \name Directory Functions
+        * \{
+        */
        /**
         * \brief Find an directory entry by name
         * \param Node  Pointer to this node
@@ -125,9 +233,13 @@ typedef struct sVFS_Node {
         * \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
+        * \return Zero on Success, non-zero on error (see errno.h)
         */
         int    (*Relink)(struct sVFS_Node *Node, char *OldName, char *NewName);
+        
+        /**
+         * }
+         */
 } tVFS_Node;
 
 /**
@@ -158,7 +270,8 @@ typedef struct sVFS_Driver
 
 extern tVFS_Node       NULLNode;       //!< NULL VFS Node (Ignored/Skipped)
 /**
- * \name Simple ACLs to aid writing drivers
+ * \name Static ACLs
+ * \brief Simple ACLs to aid writing drivers
  * \{
  */
 extern tVFS_ACL        gVFS_ACL_EveryoneRWX;   //!< Everyone Read/Write/Execute
@@ -193,8 +306,15 @@ extern tVFS_Driver *VFS_GetFSByName(char *Name);
 extern tVFS_ACL        *VFS_UnixToAcessACL(Uint Mode, Uint Owner, Uint Group);
 
 // --- Node Cache --
-//! \name Node Cache
-//! \{
+/**
+ * \name Node Cache
+ * \brief Functions to allow a node to be cached in memory by the VFS
+ * 
+ * These functions store a node for the driver, to prevent it from having
+ * to re-generate the node on each call to FindDir. It also allows for
+ * fast cleanup when a filesystem is unmounted.
+ * \{
+ */
 /**
  * \fn int Inode_GetHandle()
  * \brief Gets a unique handle to the Node Cache
@@ -218,7 +338,7 @@ extern tVFS_Node    *Inode_GetCache(int Handle, Uint64 Inode);
  */
 extern tVFS_Node       *Inode_CacheNode(int Handle, tVFS_Node *Node);
 /**
- * \fn void Inode_UncacheNode(int Handle, Uint64 Inode)
+ * \fn int 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
@@ -231,6 +351,8 @@ extern void Inode_UncacheNode(int Handle, Uint64 Inode);
  */
 extern void    Inode_ClearCache(int Handle);
 
-//! \}
+/**
+ * \}
+ */
 
 #endif
index 2fd7fd3..e2f0344 100644 (file)
@@ -8,7 +8,7 @@
 
 // === CONSTANTS ===
 //! Maximum size of a Memory Path generated by VFS_GetMemPath
-#define        VFS_MEMPATH_SIZE        (3 + (BITS/8)*2)
+#define        VFS_MEMPATH_SIZE        (3 + (BITS/4)*2)
 /**
  * \name Flags for VFS_Open
  * \{
index bfae2a4..cfbae0f 100644 (file)
@@ -14,7 +14,55 @@ const short DAYS_BEFORE[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 3
 #define UNIX_TO_2K     ((30*365*3600*24) + (7*3600*24))        //Normal years + leap years
 
 // === PROTOTYPES ===
+ int   atoi(const char *string);
+void   itoa(char *buf, Uint num, int base, int minLength, char pad);
+ int   vsnprintf(char *__s, size_t __maxlen, const char *__format, va_list args);
+ int   sprintf(char *__s, const char *__format, ...);
+ int   tolower(int c);
+ int   strucmp(const char *Str1, const char *Str2);
+ int   strpos(const char *Str, char Ch);
+ Uint8 ByteSum(void *Ptr, int Size);
+size_t strlen(const char *__s);
+char   *strcpy(char *__str1, const char *__str2);
+char   *strncpy(char *__str1, const char *__str2, size_t max);
+ int   strcmp(const char *str1, const char *str2);
+ int   strncmp(const char *str1, const char *str2, size_t num);
+char   *strdup(const char *Str);
+ int   DivUp(int num, int dem);
+ int   strpos8(const char *str, Uint32 Search);
  int   ReadUTF8(Uint8 *str, Uint32 *Val);
+ int   WriteUTF8(Uint8 *str, Uint32 Val);
+Sint64 timestamp(int sec, int mins, int hrs, int day, int month, int year);
+Uint   rand(void);
+ int   CheckString(char *String);
+ int   CheckMem(void *Mem, int NumBytes);
+ int   ModUtil_LookupString(char **Array, char *Needle);
+ int   ModUtil_SetIdent(char *Dest, char *Value);
+
+// === EXPORTS ===
+EXPORT(atoi);
+EXPORT(itoa);
+EXPORT(vsnprintf);
+EXPORT(sprintf);
+EXPORT(tolower);
+EXPORT(strucmp);
+EXPORT(strpos);
+EXPORT(ByteSum);
+EXPORT(strlen);
+EXPORT(strcpy);
+EXPORT(strncpy);
+EXPORT(strcmp);
+EXPORT(strncmp);
+EXPORT(strdup);
+EXPORT(DivUp);
+EXPORT(strpos8);
+EXPORT(ReadUTF8);
+EXPORT(WriteUTF8);
+EXPORT(timestamp);
+EXPORT(CheckString);
+EXPORT(CheckMem);
+EXPORT(ModUtil_LookupString);
+EXPORT(ModUtil_SetIdent);
 
 // === GLOBALS ===
 static Uint    giRandomState = RANDOM_SEED;
@@ -26,9 +74,16 @@ static Uint  giRandomState = RANDOM_SEED;
 int atoi(const char *string)
 {
         int    ret = 0;
+        int    bNeg = 0;
+       
+       //Log("atoi: (string='%s')", string);
        
        // Clear non-numeric characters
-       while( !('0' <= *string && *string <= '9') )    string++;
+       while( !('0' <= *string && *string <= '9') && *string != '-' )  string++;
+       if( *string == '-' ) {
+               bNeg = 1;
+               while( !('0' <= *string && *string <= '9') )    string++;
+       }
        
        if(*string == '0')
        {
@@ -37,32 +92,34 @@ int atoi(const char *string)
                {
                        // Hex
                        string ++;
-                       for( ;; ) {
-                               ret *= 16;
-                               if('0' <= *string && *string <= '9')
+                       for( ;; string ++ )
+                       {
+                               if('0' <= *string && *string <= '9') {
+                                       ret *= 16;
                                        ret += *string - '0';
-                               else if('A' <= *string && *string <= 'F')
+                               }
+                               else if('A' <= *string && *string <= 'F') {
+                                       ret *= 16;
                                        ret += *string - 'A' + 10;
-                               else if('a' <= *string && *string <= 'f')
+                               }
+                               else if('a' <= *string && *string <= 'f') {
+                                       ret *= 16;
                                        ret += *string - 'a' + 10;
+                               }
                                else
                                        break;
-                               string ++;
                        }
                }
-               else
+               else    // Octal
                {
-                       for( ;; )
+                       for( ; '0' <= *string && *string <= '7'; string ++ )
                        {
                                ret *= 8;
-                               if('0' <= *string && *string <= '7')
-                                       ret += *string - '0';
-                               else
-                                       break;
+                               ret += *string - '0';
                        }
                }
        }
-       else
+       else    // Decimal
        {
                for( ; '0' <= *string && *string <= '9'; string++)
                {
@@ -70,6 +127,11 @@ int atoi(const char *string)
                        ret += *string - '0';
                }
        }
+       
+       if(bNeg)        ret = -ret;
+       
+       //Log("atoi: RETURN %i", ret);
+       
        return ret;
 }
 
@@ -108,7 +170,14 @@ void itoa(char *buf, Uint num, int base, int minLength, char pad)
        buf[i] = 0;
 }
 
-#define PUTCH(c)       do{if(pos==__maxlen)break;if(__s){__s[pos++]=(c);}else{pos++;}}while(0)
+/**
+ * \brief Append a character the the vsnprintf output
+ */
+#define PUTCH(c)       do{\
+       char ch=(c);\
+       if(pos==__maxlen){return pos;}\
+       if(__s){__s[pos++]=ch;}else{pos++;}\
+       }while(0)
 int vsnprintf(char *__s, size_t __maxlen, const char *__format, va_list args)
 {
        char    c, pad = ' ';
@@ -118,6 +187,10 @@ int vsnprintf(char *__s, size_t __maxlen, const char *__format, va_list args)
         int    isLongLong = 0;
        Uint64  val;
        size_t  pos = 0;
+       // Flags
+       // int  bPadLeft = 0;
+       
+       //Log("vsnprintf: (__s=%p, __maxlen=%i, __format='%s', ...)", __s, __maxlen, __format);
        
        while((c = *__format++) != 0)
        {
@@ -125,6 +198,7 @@ int vsnprintf(char *__s, size_t __maxlen, const char *__format, va_list args)
                if(c != '%') { PUTCH(c); continue; }
                
                c = *__format++;
+               //Log("pos = %i", pos);
                
                // Literal %
                if(c == '%') { PUTCH('%'); continue; }
@@ -140,6 +214,7 @@ int vsnprintf(char *__s, size_t __maxlen, const char *__format, va_list args)
                
                // Get Argument
                val = va_arg(args, Uint);
+               //Log("val = %x", val);
                
                // - Padding
                if(c == '0') {
@@ -210,6 +285,7 @@ int vsnprintf(char *__s, size_t __maxlen, const char *__format, va_list args)
                case 's':
                        p = (char*)(Uint)val;
                printString:
+                       //Log("p = '%s'", p);
                        if(!p)          p = "(null)";
                        while(*p)       PUTCH(*p++);
                        break;
@@ -230,7 +306,6 @@ int vsnprintf(char *__s, size_t __maxlen, const char *__format, va_list args)
        
        if(__s && pos != __maxlen)
                __s[pos] = '\0';
-               
        
        return pos;
 }
@@ -539,7 +614,7 @@ Sint64 timestamp(int sec, int mins, int hrs, int day, int month, int year)
  * \brief Pseudo random number generator
  * \note Unknown effectiveness (made up on the spot)
  */
-Uint rand()
+Uint rand(void)
 {
        Uint    old = giRandomState;
        // Get the next state value
@@ -636,17 +711,3 @@ int ModUtil_SetIdent(char *Dest, char *Value)
        strncpy(Dest, Value, 32);
        return 1;
 }
-
-EXPORT(strlen);
-EXPORT(strdup);
-EXPORT(strcmp);
-EXPORT(strncmp);
-EXPORT(strcpy);
-EXPORT(strncpy);
-
-EXPORT(timestamp);
-EXPORT(ReadUTF8);
-EXPORT(CheckMem);
-EXPORT(CheckString);
-EXPORT(ModUtil_LookupString);
-EXPORT(ModUtil_SetIdent);
diff --git a/Kernel/logging.c b/Kernel/logging.c
new file mode 100644 (file)
index 0000000..6eac233
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * Acess 2 Kernel
+ * - By John Hodge (thePowersGang)
+ *
+ * logging.c - Kernel Logging Service
+ */
+#include <acess.h>
+
+#define PRINT_ON_APPEND        1
+
+// === CONSTANTS ===
+enum eLogLevels
+{
+       LOG_LEVEL_KPANIC,
+       LOG_LEVEL_PANIC,
+       LOG_LEVEL_FATAL,
+       LOG_LEVEL_ERROR,
+       LOG_LEVEL_WARNING,
+       LOG_LEVEL_NOTICE,
+       LOG_LEVEL_LOG,
+       LOG_LEVEL_DEBUG,
+       NUM_LOG_LEVELS
+};
+const char     *csaLevelCodes[] = {"k","p","f","e","w","n","l","d"};
+
+// === TYPES ===
+typedef struct sLogEntry
+{
+       struct sLogEntry        *Next;
+       struct sLogEntry        *LevelNext;
+       Sint64  Time;
+       char    Ident[8];
+        int    Level;
+        int    Length;
+       char    Data[];
+}      tLogEntry;
+typedef struct sLogList
+{
+       tLogEntry       *Head;
+       tLogEntry       *Tail;
+}      tLogList;
+
+// === PROTOTYPES ===
+void   Log_AddEvent(char *Ident, int Level, char *Format, va_list Args);
+static void    Log_Int_PrintMessage(tLogEntry *Entry);
+void   Log_KernelPanic(char *Ident, char *Message, ...);
+void   Log_Panic(char *Ident, char *Message, ...);
+void   Log_Error(char *Ident, char *Message, ...);
+void   Log_Warning(char *Ident, char *Message, ...);
+void   Log_Notice(char *Ident, char *Message, ...);
+void   Log_Log(char *Ident, char *Message, ...);
+void   Log_Debug(char *Ident, char *Message, ...);
+//static Uint64        Log_Int_GetIdent(const char *Str);
+
+// === EXPORTS ===
+EXPORT(Log_KernelPanic);
+EXPORT(Log_Panic);
+EXPORT(Log_Error);
+EXPORT(Log_Warning);
+EXPORT(Log_Notice);
+EXPORT(Log_Log);
+EXPORT(Log_Debug);
+
+// === GLOBALS ===
+tSpinlock      glLog;
+tLogList       gLog;
+tLogList       gLog_Levels[NUM_LOG_LEVELS];
+
+// === CODE ===
+/**
+ * \brief Adds an event to the log
+ */
+void Log_AddEvent(char *Ident, int Level, char *Format, va_list Args)
+{
+        int    len;
+       tLogEntry       *ent;
+       
+       if( Level >= NUM_LOG_LEVELS )   return;
+       
+       len = vsnprintf(NULL, 256, Format, Args);
+       
+       //Log("len = %i", len);
+       
+       ent = malloc(sizeof(tLogEntry)+len+1);
+       ent->Time = now();
+       strncpy(ent->Ident, Ident, 7);
+       ent->Level = Level;
+       ent->Length = len;
+       vsnprintf( ent->Data, 256, Format, Args );
+       
+       //Log("ent->Ident = '%s'", ent->Ident);
+       //Log("ent->Data = '%s'", ent->Data);
+       
+       LOCK( &glLog );
+       
+       ent->Next = gLog.Tail;
+       if(gLog.Head)
+               gLog.Tail = ent;
+       else
+               gLog.Tail = gLog.Head = ent;
+       
+       ent->LevelNext = gLog_Levels[Level].Tail;
+       if(gLog_Levels[Level].Head)
+               gLog_Levels[Level].Tail = ent;
+       else
+               gLog_Levels[Level].Tail = gLog_Levels[Level].Head = ent;
+       
+       RELEASE( &glLog );
+       
+       #if PRINT_ON_APPEND
+       Log_Int_PrintMessage( ent );
+       #endif
+       
+}
+
+/**
+ * \brief Prints a log message to the debug console
+ */
+void Log_Int_PrintMessage(tLogEntry *Entry)
+{
+       LogF("%018lli%s [%+8s] %s\n",
+               Entry->Time,
+               csaLevelCodes[Entry->Level],
+               Entry->Ident,
+               Entry->Data
+               );
+}
+
+/**
+ * \brief KERNEL PANIC!!!!
+ */
+void Log_KernelPanic(char *Ident, char *Message, ...)
+{
+       va_list args;   
+       va_start(args, Message);
+       Log_AddEvent(Ident, LOG_LEVEL_KPANIC, Message, args);
+       va_end(args);
+}
+
+/**
+ * \brief Panic Message - Driver Unrecoverable error
+ */
+void Log_Panic(char *Ident, char *Message, ...)
+{
+       va_list args;   
+       va_start(args, Message);
+       Log_AddEvent(Ident, LOG_LEVEL_PANIC, Message, args);
+       va_end(args);
+}
+
+/**
+ * \brief Error Message - Recoverable Error
+ */
+void Log_Error(char *Ident, char *Message, ...)
+{
+       va_list args;   
+       va_start(args, Message);
+       Log_AddEvent(Ident, LOG_LEVEL_ERROR, Message, args);
+       va_end(args);
+}
+
+/**
+ * \brief Warning Message - Something the user should know
+ */
+void Log_Warning(char *Ident, char *Message, ...)
+{
+       va_list args;
+       
+       va_start(args, Message);
+       Log_AddEvent(Ident, LOG_LEVEL_WARNING, Message, args);
+       va_end(args);
+}
+
+/**
+ * \brief Notice Message - Something the user might like to know
+ */
+void Log_Notice(char *Ident, char *Message, ...)
+{
+       va_list args;   
+       va_start(args, Message);
+       Log_AddEvent(Ident, LOG_LEVEL_NOTICE, Message, args);
+       va_end(args);
+}
+
+/**
+ * \brief Log Message - Possibly useful information
+ */
+void Log_Log(char *Ident, char *Message, ...)
+{
+       va_list args;   
+       va_start(args, Message);
+       Log_AddEvent(Ident, LOG_LEVEL_LOG, Message, args);
+       va_end(args);
+}
+
+/**
+ * \brief Debug Message - Only a developer would want this info
+ */
+void Log_Debug(char *Ident, char *Message, ...)
+{
+       va_list args;   
+       va_start(args, Message);
+       Log_AddEvent(Ident, LOG_LEVEL_DEBUG, Message, args);
+       va_end(args);
+}
index e4f49b2..eb742d4 100644 (file)
@@ -2,19 +2,24 @@
  * Acess2
  * - Module Loader
  */
+#define DEBUG  0
 #include <acess.h>
 #include <modules.h>
 
 #define        USE_EDI 0
-#define        USE_UDI 1
+#define        USE_UDI 0
 
 // === PROTOTYPES ===
- int   Modules_LoadBuiltins();
+ int   Modules_LoadBuiltins(void);
+ int   Module_RegisterLoader(tModuleLoader *Loader);
  int   Module_LoadMem(void *Buffer, Uint Length, char *ArgString);
  int   Module_LoadFile(char *Path, char *ArgString);
  int   Module_int_ResolveDeps(tModule *Info);
  int   Module_IsLoaded(char *Name);
 
+// === EXPORTS ===
+EXPORT(Module_RegisterLoader);
+
 // === IMPORTS ===
 #if USE_UDI
 extern int     UDI_LoadDriver(void *Base);
@@ -25,95 +30,139 @@ extern void        gKernelModulesEnd;
 
 // === GLOBALS ===
  int   giNumBuiltinModules = 0;
- int   giModuleSpinlock = 0;
+tSpinlock      glModuleSpinlock;
 tModule        *gLoadedModules = NULL;
 tModuleLoader  *gModule_Loaders = NULL;
+tModule        *gLoadingModules = NULL;
 
 // === CODE ===
-int Modules_LoadBuiltins()
+/**
+ * \brief Initialises a module
+ * \param Module       Pointer to the module header
+ * \return Zero on success, eModuleErrors or -1 on error
+ * \retval -1  Returned if a dependency fails, or a circular dependency
+ *              exists.
+ * \retval 0   Returned on success
+ * \retval >0  Error code form the module's initialisation function
+ */
+int Module_int_Initialise(tModule *Module)
 {
-        int    i, j, k;
-        int    numToInit = 0;
-       Uint8   *baIsLoaded;
+        int    i, j;
+        int    ret;
        char    **deps;
+       tModule *mod;
        
-       giNumBuiltinModules = (Uint)&gKernelModulesEnd - (Uint)&gKernelModules;
-       giNumBuiltinModules /= sizeof(tModule);
+       ENTER("pModule", Module);
        
-       baIsLoaded = calloc( giNumBuiltinModules, sizeof(*baIsLoaded) );
+       deps = Module->Dependencies;
        
-       // Pass 1 - Are the dependencies compiled in?
-       for( i = 0; i < giNumBuiltinModules; i++ )
+       // Check if the module has been loaded
+       for( mod = gLoadedModules; mod; mod = mod->Next )
        {
-               deps = gKernelModules[i].Dependencies;
-               if(deps)
-               {
-                       for( j = 0; deps[j]; j++ )
-                       {
-                               for( k = 0; k < giNumBuiltinModules; k++ ) {
-                                       if(strcmp(deps[j], gKernelModules[k].Name) == 0)
-                                               break;
-                               }
-                               if(k == giNumBuiltinModules) {
-                                       Warning("Unable to find dependency '%s' for '%s' in kernel",
-                                               deps[j], gKernelModules[i].Name);
-                                       
-                                       baIsLoaded[i] = -1;     // Don't Load
-                                       break;
-                               }
-                       }
-               }
-               numToInit ++;
+               if(mod == Module)       LEAVE_RET('i', 0);
        }
        
-       // Pass 2 - Intialise
-       while(numToInit)
+       // Add to the "loading" (prevents circular deps)
+       Module->Next = gLoadingModules;
+       gLoadingModules = Module;
+       
+       // Scan dependency list
+       for( j = 0; deps && deps[j]; j++ )
        {
-               for( i = 0; i < giNumBuiltinModules; i++ )
+               // Check if the module is already loaded
+               for( mod = gLoadedModules; mod; mod = mod->Next )
                {
-                       if( baIsLoaded[i] )     continue;       // Ignore already loaded modules
+                       if(strcmp(deps[j], mod->Name) == 0)
+                               break;
+               }
+               if( mod )       continue;       // Dependency is loaded, check the rest
                
-                       deps = gKernelModules[i].Dependencies;
-                       
-                       if( deps )
-                       {
-                               for( j = 0; deps[j]; j++ )
-                               {
-                                       for( k = 0; k < giNumBuiltinModules; k++ ) {
-                                               if(strcmp(deps[j], gKernelModules[k].Name) == 0)
-                                                       break;
-                                       }
-                                       // `k` is assumed to be less than `giNumBuiltinModules`
-                                       
-                                       // If a dependency failed, skip and mark as failed
-                                       if( baIsLoaded[k] == -1 ) {
-                                               baIsLoaded[i] = -1;
-                                               numToInit --;
-                                               break;
-                                       }
-                                       // If a dependency is not intialised, skip
-                                       if( !baIsLoaded[k] )    break;
-                               }
-                               // Check if we broke out
-                               if( deps[j] )   continue;
-                       }
-                       
-                       // All Dependencies OK? Initialise
-                       StartupPrint(gKernelModules[i].Name);
-                       Log("Initialising %p '%s' v%i.%i...",
-                               &gKernelModules[i],
-                               gKernelModules[i].Name,
-                               gKernelModules[i].Version>>8, gKernelModules[i].Version & 0xFF
-                               );
-                       if( gKernelModules[i].Init(NULL) == 0 ) {
-                               Log("Loading Failed, all modules that depend on this will also fail");
-                               baIsLoaded[i] = -1;
-                       }
-                       // Mark as loaded
-                       else
-                               baIsLoaded[i] = 1;
-                       numToInit --;
+               // Ok, check if it's loading
+               for( mod = gLoadingModules->Next; mod; mod = mod->Next )
+               {
+                       if(strcmp(deps[j], mod->Name) == 0)
+                               break;
+               }
+               if( mod ) {
+                       Log_Warning("Module", "Circular dependency detected");
+                       LEAVE_RET('i', -1);
+               }
+               
+               // So, if it's not loaded, we better load it then
+               for( i = 0; i < giNumBuiltinModules; i ++ )
+               {
+                       if( strcmp(deps[j], gKernelModules[i].Name) == 0 )
+                               break;
+               }
+               if( i == giNumBuiltinModules ) {
+                       Log_Warning("Module", "Dependency '%s' for module '%s' failed");
+                       return -1;
+               }
+               
+               // Dependency is not loaded, so load it
+               ret = Module_int_Initialise( &gKernelModules[i] );
+               if( ret )
+               {
+                       // The only "ok" error is NOTNEEDED
+                       if(ret != MODULE_ERR_NOTNEEDED)
+                               LEAVE_RET('i', -1);
+               }
+       }
+       
+       // All Dependencies OK? Initialise
+       StartupPrint(Module->Name);
+       Log_Log("Module", "Initialising %p '%s' v%i.%i...",
+               Module, Module->Name,
+               Module->Version >> 8, Module->Version & 0xFF
+               );
+       
+       ret = Module->Init(NULL);
+       if( ret != MODULE_ERR_OK ) {
+               switch(ret)
+               {
+               case MODULE_ERR_MISC:
+                       Log_Warning("Module", "Unable to load, reason: Miscelanious");
+                       break;
+               case MODULE_ERR_NOTNEEDED:
+                       Log_Warning("Module", "Unable to load, reason: Module not needed");
+                       break;
+               case MODULE_ERR_MALLOC:
+                       Log_Warning("Module", "Unable to load, reason: Error in malloc/realloc/calloc, probably not good");
+                       break;
+               default:
+                       Log_Warning("Module", "Unable to load reason - Unknown code %i", ret);
+                       break;
                }
+               LEAVE_RET('i', ret);
+               return ret;
+       }
+       
+       // Remove from loading list
+       gLoadingModules = gLoadingModules->Next;
+       
+       // Add to loaded list
+       LOCK( &glModuleSpinlock );
+       Module->Next = gLoadedModules;
+       gLoadedModules = Module;
+       RELEASE( &glModuleSpinlock );
+       
+       LEAVE_RET('i', 0);
+}
+
+/**
+ * \brief Initialises builtin modules
+ */
+int Modules_LoadBuiltins()
+{
+        int    i;
+       
+       // Count modules
+       giNumBuiltinModules = (Uint)&gKernelModulesEnd - (Uint)&gKernelModules;
+       giNumBuiltinModules /= sizeof(tModule);
+       
+       for( i = 0; i < giNumBuiltinModules; i++ )
+       {
+               Module_int_Initialise( &gKernelModules[i] );
        }
        
        return 0;
@@ -160,7 +209,7 @@ int Module_LoadFile(char *Path, char *ArgString)
        
        // Error check
        if(base == NULL) {
-               Warning("Module_LoadFile: Unable to load '%s'", Path);
+               Log_Warning("Module", "Module_LoadFile - Unable to load '%s'", Path);
                return 0;
        }
        
@@ -186,9 +235,9 @@ int Module_LoadFile(char *Path, char *ArgString)
                // Unknown module type?, return error
                Binary_Unload(base);
                #if USE_EDI
-               Warning("Module_LoadFile: Module has neither a Module Info struct, nor an EDI entrypoint");
+               Log_Warning("Module", "Module '%s' has neither a Module Info struct, nor an EDI entrypoint", Path);
                #else
-               Warning("Module_LoadFile: Module does not have a Module Info struct");
+               Log_Warning("Module", "Module '%s' does not have a Module Info struct", Path);
                #endif
                return 0;
        }
@@ -196,24 +245,31 @@ int Module_LoadFile(char *Path, char *ArgString)
        // Check magic number
        if(info->Magic != MODULE_MAGIC)
        {
-               Warning("Module_LoadFile: Module's magic value is invalid (0x%x != 0x%x)", info->Magic, MODULE_MAGIC);
+               Log_Warning("Module", "Module's magic value is invalid (0x%x != 0x%x)", info->Magic, MODULE_MAGIC);
                return 0;
        }
        
        // Check Architecture
        if(info->Arch != MODULE_ARCH_ID)
        {
-               Warning("Module_LoadFile: Module is for a different architecture");
+               Log_Warning("Module", "Module is for a different architecture");
                return 0;
        }
        
+       #if 1
+       if( Module_int_Initialise( info ) )
+       {
+               Binary_Unload(base);
+               return 0;
+       }
+       #else
        // Resolve Dependencies
        if( !Module_int_ResolveDeps(info) ) {
                Binary_Unload(base);
                return 0;
        }
        
-       Log("Initialising %p '%s' v%i.%i...",
+       Log_Log("Module", "Initialising %p '%s' v%i.%i...",
                                info,
                                info->Name,
                                info->Version>>8, info->Version & 0xFF
@@ -228,10 +284,11 @@ int Module_LoadFile(char *Path, char *ArgString)
        }
        
        // Add to list
-       LOCK( &giModuleSpinlock );
+       LOCK( &glModuleSpinlock );
        info->Next = gLoadedModules;
        gLoadedModules = info;
-       RELEASE( &giModuleSpinlock );
+       RELEASE( &glModuleSpinlock );
+       #endif
        
        return 1;
 }
@@ -251,7 +308,7 @@ int Module_int_ResolveDeps(tModule *Info)
        {
                // Check if the module is loaded
                if( !Module_IsLoaded(*names) ) {
-                       Warning("Module `%s' requires `%s', which is not loaded\n", Info->Name, *names);
+                       Log_Warning("Module", "Module `%s' requires `%s', which is not loaded\n", Info->Name, *names);
                        return 0;
                }
        }
index 523b3f2..cafe7c2 100644 (file)
@@ -168,7 +168,7 @@ void SyscallHandler(tSyscallRegs *Regs)
                if( !Syscall_ValidString(Regs->Arg1)
                ||  !Syscall_Valid(sizeof(Uint), Regs->Arg2) ) {
                        err = -EINVAL;
-                       ret = -1;
+                       ret = 0;
                        break;
                }
                // Path, *Entrypoint
index 80af7d1..546b2d8 100644 (file)
@@ -6,6 +6,9 @@
 #define DEBUG  0
 #include <acess.h>
 
+#define N_VARIABLES    16
+#define N_MAX_ARGS     BITS
+
 // === TYPES ===
 typedef struct
 {
@@ -18,10 +21,19 @@ typedef struct
         int    nLines;
        tConfigLine     Lines[];
 }      tConfigFile;
+typedef struct
+{
+       char    *Name;          // Name
+        int    MinArgs;        // Minimum number of arguments
+        int    MaxArgs;        // Maximum number of arguments
+       Uint    IntArgs;        // Bitmap of arguments that should be treated as integers
+       void    *Func;          // Function pointer
+       Uint    OptDefaults[N_MAX_ARGS];        // Default values for optional arguments
+}      tConfigCommand;
 
 // === IMPORTS ===
 extern int     Modules_LoadBuiltins();
-extern int     PCI_Install();
+//extern int   PCI_Install();
 extern void    DMA_Install();
 extern void    Debug_SetKTerminal(char *File);
 extern void    StartupPrint(char *Str);
@@ -34,30 +46,39 @@ void        System_ParseSetting(char *Arg);
 void   System_ExecuteScript();
 tConfigFile    *System_Int_ParseFile(char *File);
 
+// === CONSTANTS ===
+const tConfigCommand   caConfigCommands[] = {
+       {"module", 1,2, 0, Module_LoadFile, {(Uint)"",0}},      // Load a module from a file
+       {"spawn", 1,1, 0, Proc_Spawn, {0}},             // Spawn a process
+       // --- VFS ---
+       {"mount", 3,4, 0, VFS_Mount, {(Uint)"",0}},             // Mount a device
+       {"symlink", 2,2, 0, VFS_Symlink, {0}},  // Create a Symbolic Link
+       {"mkdir", 1,1, 0, VFS_MkDir, {0}},              // Create a Directory
+       {"open", 1,2, 0, VFS_Open, {VFS_OPENFLAG_READ,0}},      // Open a file
+       {"close", 1,1, 0x1, VFS_Close, {0}},    // Close an open file
+       {"ioctl", 3,3, 0x3, VFS_IOCtl, {0}},    // Call an IOCtl
+       
+       {"", 0,0, 0, NULL, {0}}
+};
+#define NUM_CONFIG_COMMANDS    (sizeof(caConfigCommands)/sizeof(caConfigCommands[0]))
+
 // === GLOBALS ===
 char   *gsConfigScript = "/Acess/Conf/BootConf.cfg";
 
 // === CODE ===
 void System_Init(char *ArgString)
 {
-       // - Start Builtin Drivers & Filesystems
-       StartupPrint("Scanning PCI Bus...");
-       PCI_Install();
-       StartupPrint("Loading DMA...");
-       DMA_Install();
-       StartupPrint("Loading staticly compiled modules...");
-       Modules_LoadBuiltins();
-       
-       // Set the debug to be echoed to the terminal
-       StartupPrint("Kernel now echoes to VT6 (Ctrl-Alt-F7)");
-       Debug_SetKTerminal("/Devices/VTerm/6");
        
        // - Parse Kernel's Command Line
        System_ParseCommandLine(ArgString);
        
        // - Execute the Config Script
-       Log("Executing config script...");
+       Log_Log("Config", "Executing config script...");
        System_ExecuteScript();
+       
+       // Set the debug to be echoed to the terminal
+       Log_Log("Config", "Kernel now echoes to VT7 (Ctrl-Alt-F8)");
+       Debug_SetKTerminal("/Devices/VTerm/7");
 }
 
 /**
@@ -71,14 +92,16 @@ void System_ParseCommandLine(char *ArgString)
         int    i;
        char    *str;
        
-       Log("Kernel Command Line: \"%s\"", ArgString);
+       Log_Log("Config", "Kernel Invocation \"%s\"", ArgString);
        
        // --- Get Arguments ---
        str = ArgString;
        for( argc = 0; argc < 32; argc++ )
        {
-               while(*str == ' ')      str++;  // Eat Whitespace
-               if(*str == '\0') {      argc--; break;} // End of string
+               // Eat Whitespace
+               while(*str == ' ')      str++;
+               // Check for the end of the string
+               if(*str == '\0') {      argc--; break;} 
                argv[argc] = str;
                while(*str && *str != ' ')
                {
@@ -88,7 +111,7 @@ void System_ParseCommandLine(char *ArgString)
                        }*/
                        str++;
                }
-               if(*str == '\0')        break;  // End of string
+               if(*str == '\0')        break;  // Check for EOS
                *str = '\0';    // Cap off argument string
                str ++; // and increment the string pointer
        }
@@ -120,7 +143,7 @@ void System_ParseVFS(char *Arg)
        
        // Check if the equals was found
        if( *value == '\0' ) {
-               Warning("Expected '=' in the string '%s'", Arg);
+               Log_Warning("Config", "Expected '=' in the string '%s'", Arg);
                return ;
        }
        
@@ -131,7 +154,7 @@ void System_ParseVFS(char *Arg)
        // - Symbolic Link <link>=<destination>
        if(value[0] == '/')
        {
-               Log("Symbolic link '%s' pointing to '%s'", Arg, value);
+               Log_Log("Config", "Symbolic link '%s' pointing to '%s'", Arg, value);
                VFS_Symlink(Arg, value);
        }
        // - Mount <mountpoint>=<fs>:<device>
@@ -146,13 +169,13 @@ void System_ParseVFS(char *Arg)
                }
                // Create Mountpoint
                if( (fd = VFS_Open(Arg, 0)) == -1 ) {
-                       Log("Creating directory '%s'", Arg, value);
+                       Log_Log("Config", "Creating directory '%s'", Arg, value);
                        VFS_MkDir( Arg );
                } else {
                        VFS_Close(fd);
                }
                // Mount
-               Log("Mounting '%s' to '%s' ('%s')", dev, Arg, value);
+               Log_Log("Config", "Mounting '%s' to '%s' ('%s')", dev, Arg, value);
                VFS_Mount(dev, Arg, value, "");
        }
 }
@@ -172,10 +195,10 @@ void System_ParseSetting(char *Arg)
        // Check for boolean/flag (no '=')
        if(*value == '\0')
        {
-               if(strcmp(Arg, "") == 0) {
-               } else {
-                       Warning("Kernel flag '%s' is not recognised", Arg);
-               }
+               //if(strcmp(Arg, "") == 0) {
+               //} else {
+                       Log_Warning("Config", "Kernel flag '%s' is not recognised", Arg);
+               //}
        }
        else
        {
@@ -183,10 +206,13 @@ void System_ParseSetting(char *Arg)
                value ++;       // and eat it's position
                
                if(strcmp(Arg, "SCRIPT") == 0) {
-                       Log("Config Script: '%s'", value);
-                       gsConfigScript = value;
+                       Log_Log("Config", "Config Script: '%s'", value);
+                       if(strlen(value) == 0)
+                               gsConfigScript = NULL;
+                       else
+                               gsConfigScript = value;
                } else {
-                       Warning("Kernel config setting '%s' is not recognised", Arg);
+                       Log_Warning("Config", "Kernel config setting '%s' is not recognised", Arg);
                }
                
        }
@@ -199,15 +225,20 @@ void System_ExecuteScript()
 {
         int    fp;
         int    fLen = 0;
-        int    i;
+        int    i, j, k;
+        int    val;
+        int    result = 0;
+        int    variables[N_VARIABLES];
+        int    bReplaced[N_MAX_ARGS];
        char    *fData;
+       char    *jmpTarget;
        tConfigFile     *file;
        tConfigLine     *line;
        
        // Open Script
        fp = VFS_Open(gsConfigScript, VFS_OPENFLAG_READ);
        if(fp == -1) {
-               Warning("[CFG] Passed script '%s' does not exist", gsConfigScript);
+               Log_Warning("Config", "Passed script '%s' does not exist", gsConfigScript);
                return;
        }
        
@@ -221,93 +252,158 @@ void System_ExecuteScript()
        VFS_Close(fp);
        
        
-       
        // Parse File
        file = System_Int_ParseFile(fData);
        
-       // Loop lines
+       // Parse each line
        for( i = 0; i < file->nLines; i++ )
        {
                line = &file->Lines[i];
                if( line->nParts == 0 ) continue;       // Skip blank
                
-               // Mount
-               if( strcmp(line->Parts[0], "mount") == 0 ) {
-                       if( line->nParts != 4 ) {
-                               Warning("Configuration command 'mount' requires 3 arguments, %i given",
-                                       line->nParts-1);
-                               continue;
+               if(line->Parts[0][0] == ':')    continue;       // Ignore labels
+               
+               // Prescan and eliminate variables
+               for( j = 1; j < line->nParts; j++ ) {
+                       Log_Debug("Config", "Arg #%i is '%s'", j, line->Parts[j]);
+                       bReplaced[j] = 0;
+                       if( line->Parts[j][0] != '$' )  continue;
+                       if( line->Parts[j][1] == '?' ) {
+                               val = result;
                        }
-                       //Log("[CFG ] Mount '%s' to '%s' (%s)",
-                       //      line->Parts[1], line->Parts[2], line->Parts[3]);
-                       //! \todo Use an optional 4th argument for the options string
-                       VFS_Mount(line->Parts[1], line->Parts[2], line->Parts[3], "");
-               }
-               // Module
-               else if(strcmp(line->Parts[0], "module") == 0) {
-                       if( line->nParts < 2 || line->nParts > 3 ) {
-                               Warning("Configuration command 'module' requires 1 or 2 arguments, %i given",
-                                       line->nParts-1);
-                               continue;
+                       else {
+                               val = atoi( &line->Parts[j][1] );
+                               if( val < 0 || val > N_VARIABLES )      continue;
+                               val = variables[ val ];
                        }
-                       if( line->nParts == 3 )
-                               Module_LoadFile(line->Parts[1], line->Parts[2]);
-                       else
-                               Module_LoadFile(line->Parts[1], "");
+                       Log_Debug("Config", "Replaced arg %i ('%s') with 0x%x", j, line->Parts[j], val);
+                       line->Parts[j] = malloc( BITS/8+2+1 );
+                       sprintf(line->Parts[j], "0x%x", val);
+                       bReplaced[j] = 1;
                }
-               // UDI Module
-               else if(strcmp(line->Parts[0], "udimod") == 0) {
-                       if( line->nParts != 2 ) {
-                               Warning("Configuration command 'udimod' requires 1 argument, %i given",
-                                       line->nParts-1);
-                               continue;
+               
+               for( j = 0; j < NUM_CONFIG_COMMANDS; j++ )
+               {
+                       Uint    args[N_MAX_ARGS];
+                       if(strcmp(line->Parts[0], caConfigCommands[j].Name) != 0)       continue;
+                       
+                       Log_Debug("Config", "Command '%s', %i args passed", line->Parts[0], line->nParts-1);
+                       
+                       if( line->nParts - 1 < caConfigCommands[j].MinArgs ) {
+                               Log_Warning("Config",
+                                       "Configuration command '%s' requires at least %i arguments, %i given",
+                                       caConfigCommands[j].Name, caConfigCommands[j].MinArgs, line->nParts-1
+                                       );
+                               break;
                        }
-                       Log("[CFG  ] Load UDI Module '%s'", line->Parts[1]);
-                       Module_LoadFile(line->Parts[1], "");
-               }
-               // EDI Module
-               else if(strcmp(line->Parts[0], "edimod") == 0) {
-                       if( line->nParts != 2 ) {
-                               Warning("Configuration command 'edimod' requires 1 argument, %i given",
-                                       line->nParts-1);
-                               continue;
+                       
+                       if( line->nParts - 1 > caConfigCommands[j].MaxArgs ) {
+                               Log_Warning("Config",
+                                       "Configuration command '%s' takes at most %i arguments, %i given",
+                                       caConfigCommands[j].Name, caConfigCommands[j].MaxArgs, line->nParts-1
+                                       );
+                               break;
+                       }
+                       
+                       for( k = caConfigCommands[j].MaxArgs-1; k > line->nParts - 1; k-- ) {
+                               args[k] = caConfigCommands[j].OptDefaults[k];
+                       }
+                       
+                       for( k = line->nParts-1; k--; )
+                       {
+                               if( caConfigCommands[j].IntArgs & (1 << k) ) {
+                                       args[k] = atoi(line->Parts[k+1]);
+                               }
+                               else {
+                                       args[k] = (Uint)line->Parts[k+1];
+                               }
+                               Log_Debug("Config", "args[%i] = 0x%x", k, args[k]);
                        }
-                       Log("[CFG  ] Load EDI Module '%s'", line->Parts[1]);
-                       Module_LoadFile(line->Parts[1], "");
+                       result = CallWithArgArray(caConfigCommands[j].Func, caConfigCommands[j].MaxArgs, args);
+                       Log_Debug("Config", "result = %i", result);
+                       break;
                }
-               // Symbolic Link
-               else if(strcmp(line->Parts[0], "symlink") == 0) {
-                       if( line->nParts != 3 ) {
-                               Warning("Configuration command 'symlink' requires 2 arguments, %i given",
+               if( j < NUM_CONFIG_COMMANDS )   continue;
+                       
+               // --- State and Variables ---
+               if(strcmp(line->Parts[0], "set") == 0)
+               {
+                        int    to, value;
+                       if( line->nParts-1 != 2 ) {
+                               Log_Warning("Config", "Configuration command 'set' requires 2 arguments, %i given",
                                        line->nParts-1);
                                continue;
                        }
-                       Log("[CFG  ] Symlink '%s' pointing to '%s'",
-                               line->Parts[1], line->Parts[2]);
-                       VFS_Symlink(line->Parts[1], line->Parts[2]);
+                       
+                       to = atoi(line->Parts[1]);
+                       value = atoi(line->Parts[2]);
+                       
+                       variables[to] = value;
+                       result = value;
                }
-               // Create Directory
-               else if(strcmp(line->Parts[0], "mkdir") == 0) {
-                       if( line->nParts != 2 ) {
-                               Warning("Configuration command 'mkdir' requires 1 argument, %i given",
+               // if <val1> <op> <val2> <dest>
+               else if(strcmp(line->Parts[0], "if") == 0)
+               {
+                       if( line->nParts-1 != 4 ) {
+                               Log_Warning("Config", "Configuration command 'if' requires 4 arguments, %i given",
                                        line->nParts-1);
-                               continue;
                        }
-                       Log("[CFG  ] New Directory '%s'", line->Parts[1]);
-                       VFS_MkDir(line->Parts[1]);
+                       
+                       result = atoi(line->Parts[1]);
+                       val = atoi(line->Parts[3]);
+                       
+                       jmpTarget = line->Parts[4];
+                       
+                       Log_Log("Config", "IF 0x%x %s 0x%x THEN GOTO %s",
+                               result, line->Parts[2], val, jmpTarget);
+                       
+                       if( strcmp(line->Parts[2], "<" ) == 0 ) {
+                               if( result < val )      goto jumpToLabel;
+                       }
+                       else if( strcmp(line->Parts[2], "<=") == 0 ) {
+                               if( result <= val )     goto jumpToLabel;
+                       }
+                       else if( strcmp(line->Parts[2], ">" ) == 0 ) {
+                               if (result > val )      goto jumpToLabel;
+                       }
+                       else if( strcmp(line->Parts[2], ">=") == 0 ) {
+                               if( result >= val )     goto jumpToLabel;
+                       }
+                       else if( strcmp(line->Parts[2],  "=") == 0 ) {
+                               if( result == val )     goto jumpToLabel;
+                       }
+                       else if( strcmp(line->Parts[2], "!=") == 0 ) {
+                               if( result != val )     goto jumpToLabel;
+                       }
+                       else {
+                               Log_Warning("Config", "Unknown comparision '%s' in `if`", line->Parts[2]);
+                       }
+                       
                }
-               // Spawn a process
-               else if(strcmp(line->Parts[0], "spawn") == 0) {
-                       if( line->nParts != 2 ) {
-                               Warning("Configuration command 'spawn' requires 1 argument, %i given",
+               else if(strcmp(line->Parts[0], "goto") == 0) {
+                       if( line->nParts-1 != 1 ) {
+                               Log_Warning("Config", "Configuration command 'goto' requires 1 arguments, %i given",
                                        line->nParts-1);
-                               continue;
                        }
-                       Log("[CFG  ] Starting '%s' as a new task", line->Parts[1]);
-                       Proc_Spawn(line->Parts[1]);
+                       jmpTarget = line->Parts[1];
+               
+               jumpToLabel:
+                       for( j = 0; j < file->nLines; j ++ )
+                       {
+                               if(file->Lines[j].nParts == 0)
+                                       continue;
+                               if(file->Lines[j].Parts[0][0] != ':')
+                                       continue;
+                               if( strcmp(file->Lines[j].Parts[0]+1, jmpTarget) == 0)
+                                       break;
+                       }
+                       if( j == file->nLines )
+                               Log_Warning("Config", "Unable to find label '%s'", jmpTarget);
+                       else
+                               i = j;
                }
                else {
-                       Warning("Unknown configuration command '%s' on line %i",
+                       Log_Warning("Config", "Unknown configuration command '%s' on line %i",
                                line->Parts[0],
                                line->TrueLine
                                );
@@ -317,6 +413,10 @@ void System_ExecuteScript()
        // Clean up after ourselves
        for( i = 0; i < file->nLines; i++ ) {
                if( file->Lines[i].nParts == 0 )        continue;       // Skip blank
+               for( j = 0; j < file->Lines[i].nParts; j++ ) {
+                       if(IsHeap(file->Lines[i].Parts[j]))
+                               free(file->Lines[i].Parts[j]);
+               }
                free( file->Lines[i].Parts );
        }
        free( file );
@@ -437,6 +537,7 @@ tConfigFile *System_Int_ParseFile(char *FileData)
                        // Quoted
                        if( *ptr == '"' ) {
                                ptr ++;
+                               ret->Lines[i].Parts[j] = ptr;
                                while( *ptr && !(*ptr == '"' && ptr[-1] == '\\') && *ptr != '\n' )
                                        ptr++;
                        }
index 075350d..96a38da 100644 (file)
@@ -25,7 +25,7 @@ extern int    Proc_Clone(Uint *Err, Uint Flags);
 
 // === PROTOTYPES ===
 void   Threads_Init();
-void   Threads_SetName(char *NewName);
+ int   Threads_SetName(char *NewName);
 char   *Threads_GetName(int ID);
 void   Threads_SetTickets(int Num);
 tThread        *Threads_CloneTCB(Uint *Err, Uint Flags);
@@ -118,13 +118,14 @@ void Threads_Init()
  * \fn void Threads_SetName(char *NewName)
  * \brief Sets the current thread's name
  */
-void Threads_SetName(char *NewName)
+int Threads_SetName(char *NewName)
 {
        tThread *cur = Proc_GetCurThread();
        if( IsHeap(cur->ThreadName) )
                free( cur->ThreadName );
        cur->ThreadName = malloc(strlen(NewName)+1);
        strcpy(cur->ThreadName, NewName);
+       return 0;
 }
 
 /**
@@ -467,7 +468,7 @@ void Threads_Sleep()
        tThread *cur = Proc_GetCurThread();
        tThread *thread;
        
-       Log("Proc_Sleep: %i going to sleep", cur->TID);
+       //Log_Log("Threads", "%i going to sleep", cur->TID);
        
        // Acquire Spinlock
        LOCK( &giThreadListLock );
@@ -521,11 +522,14 @@ void Threads_Wake(tThread *Thread)
        {
        case THREAD_STAT_ACTIVE:        break;
        case THREAD_STAT_SLEEPING:
+               //Log_Log("Threads", "Waking %i (%p) from sleeping", Thread->TID, Thread);
                LOCK( &giThreadListLock );
                prev = Threads_int_GetPrev(&gSleepingThreads, Thread);
                prev->Next = Thread->Next;      // Remove from sleeping queue
                Thread->Next = gActiveThreads;  // Add to active queue
                gActiveThreads = Thread;
+               giNumActiveThreads ++;
+               giTotalTickets += Thread->NumTickets;
                Thread->Status = THREAD_STAT_ACTIVE;
                RELEASE( &giThreadListLock );
                break;
@@ -541,6 +545,11 @@ void Threads_Wake(tThread *Thread)
        }
 }
 
+void Threads_WakeTID(tTID Thread)
+{
+       Threads_Wake( Threads_GetThread(Thread) );
+}
+
 /**
  * \fn void Threads_AddActive(tThread *Thread)
  * \brief Adds a thread to the active queue
@@ -690,10 +699,15 @@ tThread *Threads_GetNextToRun(int CPU)
         int    ticket;
         int    number;
        
-       if(giNumActiveThreads == 0)     return NULL;
+       if(giNumActiveThreads == 0) {
+               //Log_Debug("Threads", "CPU%i has no threads to run", CPU);
+               return NULL;
+       }
        
        // Special case: 1 thread
        if(giNumActiveThreads == 1) {
+               //Log_Debug("Threads", "CPU%i has only one thread %i %s",
+               //      CPU, gActiveThreads->TID, gActiveThreads->ThreadName);
                return gActiveThreads;
        }
        
@@ -721,6 +735,9 @@ tThread *Threads_GetNextToRun(int CPU)
                        giTotalTickets, number);
        }
        
+       //Log_Debug("Threads", "Switching CPU%i to %p (%s)",
+       //      CPU, thread, thread->ThreadName);
+       
        return thread;
 }
 
index d396a1f..b7379ad 100644 (file)
@@ -8,7 +8,8 @@
 #include <fs_devfs.h>
 
 // === PROTOTYPES ===
- int   DevFS_AddDevice(tDevFS_Driver *Dev);
+ int   DevFS_AddDevice(tDevFS_Driver *Device);
+void   DevFS_DelDevice(tDevFS_Driver *Device);
 tVFS_Node      *DevFS_InitDevice(char *Device, char **Options);
 char   *DevFS_ReadDir(tVFS_Node *Node, int Pos);
 tVFS_Node      *DevFS_FindDir(tVFS_Node *Node, char *Name);
@@ -27,17 +28,73 @@ tVFS_Node   gDevFS_RootNode = {
        };
 tDevFS_Driver  *gDevFS_Drivers = NULL;
  int   giDevFS_NextID = 1;
+tSpinlock      glDevFS_ListLock;
 
 // === CODE ===
 /**
- * \fn int DevFS_AddDevice(tDevFS_Driver *Dev)
+ * \fn int DevFS_AddDevice(tDevFS_Driver *Device)
  */
-int DevFS_AddDevice(tDevFS_Driver *Dev)
+int DevFS_AddDevice(tDevFS_Driver *Device)
 {
-       Dev->Next = gDevFS_Drivers;
-       gDevFS_Drivers = Dev;
-       gDevFS_RootNode.Size ++;
-       return giDevFS_NextID++;
+        int    ret = 0;
+       tDevFS_Driver   *dev;
+       
+       LOCK( &glDevFS_ListLock );
+       
+       // Check if the device is already registered or the name is taken
+       for( dev = gDevFS_Drivers; dev; dev = dev->Next )
+       {
+               if(dev == Device)       break;
+               if(strcmp(dev->Name, Device->Name) == 0)        break;
+       }
+       
+       if(dev) {
+               if(dev == Device)
+                       Log_Warning("DevFS", "Device %p '%s' attempted to register itself twice",
+                               dev, dev->Name);
+               else
+                       Log_Warning("DevFS", "Device %p attempted to register '%s' which was owned by %p",
+                               Device, dev->Name, dev);
+               ret = 0;        // Error
+       }
+       else {
+               Device->Next = gDevFS_Drivers;
+               gDevFS_Drivers = Device;
+               gDevFS_RootNode.Size ++;
+               ret = giDevFS_NextID ++;
+       }
+       RELEASE( &glDevFS_ListLock );
+       
+       return ret;
+}
+
+/**
+ * \brief Delete a device from the DevFS folder
+ */
+void DevFS_DelDevice(tDevFS_Driver *Device)
+{
+       tDevFS_Driver   *prev = NULL, *dev;
+       
+       LOCK( &glDevFS_ListLock );
+       // Search list for device
+       for(dev = gDevFS_Drivers;
+               dev && dev != Device;
+               prev = dev, dev = dev->Next
+               );
+       
+       // Check if it was found
+       if(dev)
+       {
+               if(prev)
+                       prev->Next = Device->Next;
+               else
+                       gDevFS_Drivers = Device->Next;
+       }
+       else
+               Log_Warning("DevFS", "Attempted to unregister device %p '%s' which was not registered",
+                       Device, Device->Name);
+       
+       RELEASE( &glDevFS_ListLock );
 }
 
 /**
@@ -64,7 +121,10 @@ char *DevFS_ReadDir(tVFS_Node *Node, int Pos)
                dev = dev->Next
                );
        
-       return strdup(dev->Name);
+       if(dev)
+               return strdup(dev->Name);
+       else
+               return NULL;
 }
 
 /**
@@ -96,3 +156,4 @@ tVFS_Node *DevFS_FindDir(tVFS_Node *Node, char *Name)
 
 // --- EXPORTS ---
 EXPORT(DevFS_AddDevice);
+EXPORT(DevFS_DelDevice);
diff --git a/Kernel/vfs/fs/fat.c b/Kernel/vfs/fs/fat.c
deleted file mode 100644 (file)
index 3ebe89a..0000000
+++ /dev/null
@@ -1,909 +0,0 @@
-/*\r
- * Acess 2\r
- * FAT12/16/32 Driver Version (Incl LFN)\r
- */\r
-#define DEBUG  0\r
-#define VERBOSE        1\r
-\r
-#define CACHE_FAT      1       //!< Caches the FAT in memory\r
-#define USE_LFN                1       //!< Enables the use of Long File Names\r
-\r
-#include <acess.h>\r
-#include <modules.h>\r
-#include <vfs.h>\r
-#include "fs_fat.h"\r
-\r
-\r
-// === TYPES ===\r
-#if USE_LFN\r
-typedef struct s_lfncache {\r
-       Uint    Inode, Impl;\r
-        int    id;\r
-       char    Name[256];\r
-       struct s_lfncache       *Next;\r
-}      t_lfncache;\r
-#endif\r
-\r
-// === PROTOTYPES ===\r
- int   FAT_Install(char **Arguments);\r
-tVFS_Node      *FAT_InitDevice(char *device, char **options);\r
-void   FAT_Unmount(tVFS_Node *Node);\r
-Uint64 FAT_Read(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer);\r
-Uint64 FAT_Write(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer);\r
-char   *FAT_ReadDir(tVFS_Node *dirNode, int dirpos);\r
-tVFS_Node      *FAT_FindDir(tVFS_Node *dirNode, char *file);\r
- int   FAT_Mknod(tVFS_Node *Node, char *Name, Uint Flags);\r
- int   FAT_Relink(tVFS_Node *node, char *OldName, char *NewName);\r
-void   FAT_CloseFile(tVFS_Node *node);\r
-\r
-// === SEMI-GLOBALS ===\r
-MODULE_DEFINE(0, 0x51 /*v0.80*/, VFAT, FAT_Install, NULL, NULL);\r
-tFAT_VolInfo   gFAT_Disks[8];\r
- int   giFAT_PartCount = 0;\r
-#if USE_LFN\r
-t_lfncache     *fat_lfncache;\r
-#endif\r
-tVFS_Driver    gFAT_FSInfo = {\r
-       "fat", 0, FAT_InitDevice, FAT_Unmount, NULL\r
-       };\r
-\r
-// === CODE ===\r
-/**\r
- * \fn int FAT_Install(char **Arguments)\r
- * \brief \r
- */\r
-int FAT_Install(char **Arguments)\r
-{\r
-       VFS_AddDriver( &gFAT_FSInfo );\r
-       return MODULE_INIT_SUCCESS;\r
-}\r
-\r
-/**\r
- * \fn tVFS_Node *FAT_InitDevice(char *Device, char **options)\r
- * \brief Reads the boot sector of a disk and prepares the structures for it\r
- */\r
-tVFS_Node *FAT_InitDevice(char *Device, char **options)\r
-{\r
-       fat_bootsect *bs;\r
-        int    i;\r
-       Uint32  FATSz, RootDirSectors, TotSec, CountofClusters;\r
-       tVFS_Node       *node = NULL;\r
-       tFAT_VolInfo    *diskInfo = &gFAT_Disks[giFAT_PartCount];\r
-       \r
-       //Temporary Pointer\r
-       bs = &diskInfo->bootsect;\r
-       \r
-       //Open device and read boot sector\r
-       diskInfo->fileHandle = VFS_Open(Device, VFS_OPENFLAG_READ|VFS_OPENFLAG_WRITE);\r
-       if(diskInfo->fileHandle == -1) {\r
-               Warning("FAT_InitDisk - Unable to open device '%s'", Device);\r
-               return NULL;\r
-       }\r
-       \r
-       VFS_ReadAt(diskInfo->fileHandle, 0, 512, bs);\r
-       \r
-       if(bs->bps == 0 || bs->spc == 0) {\r
-               Warning("FAT_InitDisk - Error in FAT Boot Sector\n");\r
-               return NULL;\r
-       }\r
-       \r
-       //FAT Type Determining\r
-       // From Microsoft FAT Specifcation\r
-       RootDirSectors = ((bs->files_in_root*32) + (bs->bps - 1)) / bs->bps;\r
-       \r
-       if(bs->fatSz16 != 0)            FATSz = bs->fatSz16;\r
-       else                                    FATSz = bs->spec.fat32.fatSz32;\r
-       \r
-       if(bs->totalSect16 != 0)                TotSec = bs->totalSect16;\r
-       else                                            TotSec = bs->totalSect32;\r
-       \r
-       CountofClusters = (TotSec - (bs->resvSectCount + (bs->fatCount * FATSz) + RootDirSectors)) / bs->spc;\r
-       \r
-       if(CountofClusters < 4085)\r
-               diskInfo->type = FAT12;\r
-       else if(CountofClusters < 65525)\r
-               diskInfo->type = FAT16;\r
-       else\r
-               diskInfo->type = FAT32;\r
-       \r
-       #if VERBOSE\r
-       {\r
-               char    *sFatType, *sSize;\r
-               Uint    iSize = CountofClusters * bs->spc / 2;\r
-               \r
-               switch(diskInfo->type)\r
-               {\r
-               case FAT12:     sFatType = "FAT12";     break;\r
-               case FAT16:     sFatType = "FAT16";     break;\r
-               case FAT32:     sFatType = "FAT32";     break;\r
-               default:        sFatType = "UNKNOWN";   break;\r
-               }\r
-               if(iSize <= 2*1024) {\r
-                       sSize = "KiB";\r
-               }\r
-               else if(iSize <= 2*1024*1024) {\r
-                       sSize = "MiB";\r
-                       iSize >>= 10;\r
-               }\r
-               else {\r
-                       sSize = "GiB";\r
-                       iSize >>= 20;\r
-               }\r
-               Log("[FAT ] '%s' %s, %i %s", Device, sFatType, iSize, sSize);\r
-       }\r
-       #endif\r
-       \r
-       //Get Name\r
-       if(diskInfo->type == FAT32) {\r
-               for(i=0;i<11;i++)\r
-                       diskInfo->name[i] = (bs->spec.fat32.label[i] == ' ' ? '\0' : bs->spec.fat32.label[i]);\r
-       }\r
-       else {\r
-               for(i=0;i<11;i++)\r
-                       diskInfo->name[i] = (bs->spec.fat16.label[i] == ' ' ? '\0' : bs->spec.fat16.label[i]);\r
-       }\r
-       diskInfo->name[11] = '\0';\r
-       \r
-       //Compute Root directory offset\r
-       if(diskInfo->type == FAT32)\r
-               diskInfo->rootOffset = bs->spec.fat32.rootClust;\r
-       else\r
-               diskInfo->rootOffset = (FATSz * bs->fatCount) / bs->spc;\r
-       \r
-       diskInfo->clusterCount = CountofClusters;\r
-       \r
-       diskInfo->firstDataSect = bs->resvSectCount + (bs->fatCount * FATSz) + RootDirSectors;\r
-       \r
-       //Allow for Caching the FAT\r
-       #if CACHE_FAT\r
-       {\r
-       Uint32  Ofs;\r
-       diskInfo->FATCache = (Uint32*)malloc(sizeof(Uint32)*CountofClusters);\r
-       if(diskInfo->FATCache == NULL) {\r
-               Warning("FAT_InitDisk - Heap Exhausted\n");\r
-               return NULL;\r
-       }\r
-       Ofs = bs->resvSectCount*512;\r
-       if(diskInfo->type == FAT12) {\r
-               Uint32  val;\r
-                int    j;\r
-               char    buf[1536];\r
-               for(i=0;i<CountofClusters/2;i++) {\r
-                       j = i & 511;    //%512\r
-                       if( j == 0 ) {\r
-                               VFS_ReadAt(diskInfo->fileHandle, Ofs, 3*512, buf);\r
-                               Ofs += 3*512;\r
-                       }\r
-                       val = *((int*)(buf+j*3));\r
-                       diskInfo->FATCache[i*2] = val & 0xFFF;\r
-                       diskInfo->FATCache[i*2+1] = (val>>12) & 0xFFF;\r
-               }\r
-       }\r
-       if(diskInfo->type == FAT16) {\r
-               Uint16  buf[256];\r
-               for(i=0;i<CountofClusters;i++) {\r
-                       if( (i & 255) == 0 ) {\r
-                               VFS_ReadAt(diskInfo->fileHandle, Ofs, 512, buf);\r
-                               Ofs += 512;\r
-                       }\r
-                       diskInfo->FATCache[i] = buf[i&255];\r
-               }\r
-       }\r
-       if(diskInfo->type == FAT32) {\r
-               Uint32  buf[128];\r
-               for(i=0;i<CountofClusters;i++) {\r
-                       if( (i & 127) == 0 ) {\r
-                               VFS_ReadAt(diskInfo->fileHandle, Ofs, 512, buf);\r
-                               Ofs += 512;\r
-                       }\r
-                       diskInfo->FATCache[i] = buf[i&127];\r
-               }\r
-       }\r
-       LOG("FAT Fully Cached");\r
-       }\r
-       #endif /*CACHE_FAT*/\r
-       \r
-       //Initalise inode cache for FAT\r
-       diskInfo->inodeHandle = Inode_GetHandle();\r
-       LOG("Inode Cache handle is %i", diskInfo->inodeHandle);\r
-       \r
-       // == VFS Interface\r
-       node = &diskInfo->rootNode;\r
-       node->Inode = diskInfo->rootOffset;\r
-       node->Size = bs->files_in_root; // Unknown - To be set on readdir\r
-       node->ImplInt = giFAT_PartCount;\r
-       \r
-       node->ReferenceCount = 1;\r
-       \r
-       node->UID = 0;  node->GID = 0;\r
-       node->NumACLs = 1;\r
-       node->ACLs = &gVFS_ACL_EveryoneRWX;\r
-       node->Flags = VFS_FFLAG_DIRECTORY;\r
-       node->CTime = node->MTime = node->ATime = now();\r
-       \r
-       node->Read = node->Write = NULL;\r
-       node->ReadDir = FAT_ReadDir;\r
-       node->FindDir = FAT_FindDir;\r
-       node->Relink = FAT_Relink;\r
-       node->MkNod = FAT_Mknod;\r
-       //node->Close = FAT_CloseDevice;\r
-       \r
-       giFAT_PartCount ++;\r
-       return node;\r
-}\r
-\r
-/**\r
- * \fn void FAT_Unmount(tVFS_Node *Node)\r
- * \brief Closes a mount and marks it as free\r
- */\r
-void FAT_Unmount(tVFS_Node *Node)\r
-{\r
-       // Close Disk Handle\r
-       VFS_Close( gFAT_Disks[Node->ImplInt].fileHandle );\r
-       // Clear Node Cache\r
-       Inode_ClearCache(gFAT_Disks[Node->ImplInt].inodeHandle);\r
-       // Mark as unused\r
-       gFAT_Disks[Node->ImplInt].fileHandle = -2;\r
-       return;\r
-}\r
-\r
-/**\r
- * \fn static Uint32 FAT_int_GetFatValue(tFAT_VolInfo *Disk, Uint32 cluster)\r
- * \brief Fetches a value from the FAT\r
- */\r
-static Uint32 FAT_int_GetFatValue(tFAT_VolInfo *Disk, Uint32 cluster)\r
-{\r
-       Uint32  val = 0;\r
-       #if !CACHE_FAT\r
-       Uint32  ofs = Disk->bootsect.resvSectCount*512;\r
-       #endif\r
-       ENTER("pDisk xCluster", Disk, cluster);\r
-       #if CACHE_FAT\r
-       val = Disk->FATCache[cluster];\r
-       if(Disk->type == FAT12 && val == EOC_FAT12)     val = -1;\r
-       if(Disk->type == FAT16 && val == EOC_FAT16)     val = -1;\r
-       if(Disk->type == FAT32 && val == EOC_FAT32)     val = -1;\r
-       #else\r
-       if(Disk->type == FAT12) {\r
-               VFS_ReadAt(Disk->fileHandle, ofs+(cluster>>1)*3, 3, &val);\r
-               val = (cluster&1 ? val&0xFFF : val>>12);\r
-               if(val == EOC_FAT12)    val = -1;\r
-       } else if(Disk->type == FAT16) {\r
-               VFS_ReadAt(Disk->fileHandle, ofs+cluster*2, 2, &val);\r
-               if(val == EOC_FAT16)    val = -1;\r
-       } else {\r
-               VFS_ReadAt(Disk->fileHandle, ofs+cluster*4, 4, &val);\r
-               if(val == EOC_FAT32)    val = -1;\r
-       }\r
-       #endif /*CACHE_FAT*/\r
-       LEAVE('x', val);\r
-       return val;\r
-}\r
-\r
-/* Reads a cluster's data\r
- */\r
-static void FAT_int_ReadCluster(int Handle, Uint32 Cluster, int Length, void *Buffer)\r
-{\r
-       ENTER("iHandle xCluster iLength pBuffer", Handle, Cluster, Length, Buffer);\r
-       //Log("Cluster = %i (0x%x)", Cluster, Cluster);\r
-       VFS_ReadAt(\r
-               gFAT_Disks[Handle].fileHandle,\r
-               (gFAT_Disks[Handle].firstDataSect + (Cluster-2)*gFAT_Disks[Handle].bootsect.spc )\r
-                       * gFAT_Disks[Handle].bootsect.bps,\r
-               Length,\r
-               Buffer\r
-               );\r
-       LEAVE('-');\r
-}\r
-\r
-/**\r
- * \fn Uint64 FAT_Read(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer)\r
- * \brief Reads data from a specified file\r
- */\r
-Uint64 FAT_Read(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer)\r
-{\r
-        int    preSkip, count;\r
-        int    handle = node->ImplInt;\r
-        int    i, cluster, pos;\r
-        int    bpc;\r
-       void    *tmpBuf;\r
-       tFAT_VolInfo    *disk = &gFAT_Disks[node->ImplInt];\r
-       \r
-       ENTER("Xoffset Xlength pbuffer", offset, length, buffer);\r
-       \r
-       // Calculate and Allocate Bytes Per Cluster\r
-       bpc = disk->bootsect.spc * disk->bootsect.bps;\r
-       tmpBuf = (void*) malloc(bpc);\r
-       LOG("malloc'd %i bytes", bpc);\r
-       \r
-       // Cluster is stored in Inode Field\r
-       cluster = node->Inode;\r
-       \r
-       // Sanity Check offset\r
-       if(offset > node->Size) {\r
-               //LOG("Reading past EOF (%i > %i)", offset, node->Size);\r
-               LEAVE('i', 0);\r
-               return 0;\r
-       }\r
-       // Clamp Size\r
-       if(offset + length > node->Size) {\r
-               //LOG("Reading past EOF (%lli + %lli > %lli), clamped to %lli",\r
-               //      offset, length, node->Size, node->Size - offset);\r
-               length = node->Size - offset;\r
-       }\r
-       \r
-       // Single Cluster including offset\r
-       if(length + offset < bpc)\r
-       {\r
-               FAT_int_ReadCluster(handle, cluster, bpc, tmpBuf);\r
-               memcpy( buffer, (void*)( tmpBuf + offset%bpc ), length );\r
-               free(tmpBuf);\r
-               LEAVE('i', 1);\r
-               return length;\r
-       }\r
-       \r
-       preSkip = offset / bpc;\r
-       \r
-       //Skip previous clusters\r
-       for(i=preSkip;i--;)     {\r
-               cluster = FAT_int_GetFatValue(disk, cluster);\r
-               if(cluster == -1) {\r
-                       Warning("FAT_Read - Offset is past end of cluster chain mark");\r
-                       LEAVE('i', 0);\r
-                       return 0;\r
-               }\r
-       }\r
-       \r
-       // Get Count of Clusters to read\r
-       count = ((offset%bpc+length) / bpc) + 1;\r
-       \r
-       // Get buffer Position after 1st cluster\r
-       pos = bpc - offset%bpc;\r
-       \r
-       // Read 1st Cluster\r
-       FAT_int_ReadCluster(handle, cluster, bpc, tmpBuf);\r
-       memcpy(\r
-               buffer,\r
-               (void*)( tmpBuf + (bpc-pos) ),\r
-               (pos < length ? pos : length)\r
-               );\r
-       \r
-       if (count == 1) {\r
-               free(tmpBuf);\r
-               LEAVE('i', 1);\r
-               return length;\r
-       }\r
-       \r
-       cluster = FAT_int_GetFatValue(disk, cluster);\r
-       \r
-       #if DEBUG\r
-       LOG("pos=%i\n", pos);\r
-       LOG("Reading the rest of the clusters\n");\r
-       #endif\r
-       \r
-       \r
-       //Read the rest of the cluster data\r
-       for( i = 1; i < count-1; i++ )\r
-       {\r
-               FAT_int_ReadCluster(handle, cluster, bpc, tmpBuf);\r
-               memcpy((void*)(buffer+pos), tmpBuf, bpc);\r
-               pos += bpc;\r
-               cluster = FAT_int_GetFatValue(disk, cluster);\r
-               if(cluster == -1) {\r
-                       Warning("FAT_Read - Read past End of Cluster Chain");\r
-                       free(tmpBuf);\r
-                       LEAVE('i', 0);\r
-                       return 0;\r
-               }\r
-       }\r
-       \r
-       FAT_int_ReadCluster(handle, cluster, bpc, tmpBuf);\r
-       memcpy((void*)(buffer+pos), tmpBuf, length-pos);\r
-       \r
-       #if DEBUG\r
-       LOG("Free tmpBuf(0x%x) and Return\n", tmpBuf);\r
-       #endif\r
-       \r
-       free(tmpBuf);\r
-       LEAVE('X', length);\r
-       return length;\r
-}\r
-\r
-/**\r
- * \fn Uint64 FAT_Write(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer)\r
- */\r
-Uint64 FAT_Write(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer)\r
-{\r
-       return 0;\r
-}\r
-\r
-/**\r
- * \fn static void FAT_int_ProperFilename(char *dest, char *src)\r
- * \brief Converts a FAT directory entry name into a proper filename\r
- */\r
-static void FAT_int_ProperFilename(char *dest, char *src)\r
-{\r
-        int    a, b;\r
-       \r
-       for( a = 0; a < 8; a++) {\r
-               if(src[a] == ' ')       break;\r
-               dest[a] = src[a];\r
-       }\r
-       b = a;\r
-       a = 8;\r
-       if(src[8] != ' ')\r
-               dest[b++] = '.';\r
-       for( ; a < 11; a++, b++)        {\r
-               if(src[a] == ' ')       break;\r
-               dest[b] = src[a];\r
-       }\r
-       dest[b] = '\0';\r
-       #if DEBUG\r
-       //Log("FAT_int_ProperFilename: dest='%s'", dest);\r
-       #endif\r
-}\r
-\r
-/**\r
- * \fn char *FAT_int_CreateName(tVFS_Node *parent, fat_filetable *ft, char *LongFileName)\r
- * \brief Converts either a LFN or a 8.3 Name into a proper name\r
- */\r
-char *FAT_int_CreateName(tVFS_Node *parent, fat_filetable *ft, char *LongFileName)\r
-{\r
-       char    *ret;\r
-        int    len;\r
-       #if USE_LFN\r
-       if(LongFileName && LongFileName[0] != '\0')\r
-       {       \r
-               len = strlen(LongFileName);\r
-               ret = malloc(len+1);\r
-               strcpy(ret, LongFileName);\r
-       }\r
-       else\r
-       {\r
-       #endif\r
-               ret = (char*) malloc(13);\r
-               memset(ret, 13, '\0');\r
-               FAT_int_ProperFilename(ret, ft->name);\r
-       #if USE_LFN\r
-       }\r
-       #endif\r
-       return ret;\r
-}\r
-\r
-/**\r
- * \fn tVFS_Node *FAT_int_CreateNode(tVFS_Node *parent, fat_filetable *ft, char *LongFileName)\r
- * \brief Creates a tVFS_Node structure for a given file entry\r
- */\r
-tVFS_Node *FAT_int_CreateNode(tVFS_Node *parent, fat_filetable *ft, char *LongFileName)\r
-{\r
-       tVFS_Node       node = {0};\r
-       tVFS_Node       *ret;\r
-       \r
-       ENTER("pParent pFT sLongFileName", parent, ft, LongFileName);\r
-       \r
-       // Set Other Data\r
-       node.Inode = ft->cluster | (ft->clusterHi<<16);\r
-       node.Size = ft->size;\r
-       LOG("ft->size = %i", ft->size);\r
-       node.ImplInt = parent->ImplInt;\r
-       node.UID = 0;   node.GID = 0;\r
-       node.NumACLs = 1;\r
-       node.ACLs = &gVFS_ACL_EveryoneRWX;      // RWXRWXRWX\r
-       \r
-       node.Flags = 0;\r
-       if(ft->attrib & ATTR_DIRECTORY) node.Flags |= VFS_FFLAG_DIRECTORY;\r
-       if(ft->attrib & ATTR_READONLY)  node.Flags |= VFS_FFLAG_READONLY;\r
-       \r
-       node.ATime = timestamp(0,0,0,\r
-                       ((ft->adate&0x1F)-1),   //Days\r
-                       ((ft->adate&0x1E0)-1),          //Months\r
-                       1980+((ft->adate&0xFF00)>>8));  //Years\r
-       \r
-       node.CTime = ft->ctimems * 10;  //Miliseconds\r
-       node.CTime += timestamp(\r
-                       (ft->ctime&0x1F)<<1,    //Seconds\r
-                       ((ft->ctime&0x3F0)>>5), //Minutes\r
-                       ((ft->ctime&0xF800)>>11),       //Hours\r
-                       ((ft->cdate&0x1F)-1),           //Days\r
-                       ((ft->cdate&0x1E0)-1),          //Months\r
-                       1980+((ft->cdate&0xFF00)>>8));  //Years\r
-                       \r
-       node.MTime = timestamp(\r
-                       (ft->mtime&0x1F)<<1,    //Seconds\r
-                       ((ft->mtime&0x3F0)>>5), //Minuites\r
-                       ((ft->mtime&0xF800)>>11),       //Hours\r
-                       ((ft->mdate&0x1F)-1),           //Days\r
-                       ((ft->mdate&0x1E0)-1),          //Months\r
-                       1980+((ft->mdate&0xFF00)>>8));  //Years\r
-       \r
-       if(node.Flags & VFS_FFLAG_DIRECTORY) {\r
-               node.ReadDir = FAT_ReadDir;\r
-               node.FindDir = FAT_FindDir;\r
-               node.MkNod = FAT_Mknod;\r
-               node.Size = -1;\r
-       } else {\r
-               node.Read = FAT_Read;\r
-               node.Write = FAT_Write;\r
-       }\r
-       node.Close = FAT_CloseFile;\r
-       node.Relink = FAT_Relink;\r
-       \r
-       ret = Inode_CacheNode(gFAT_Disks[parent->ImplInt].inodeHandle, &node);\r
-       LEAVE('p', ret);\r
-       return ret;\r
-}\r
-\r
-#if USE_LFN\r
-/**\r
- \fn char *FAT_int_GetLFN(tVFS_Node *node)\r
- \brief Return pointer to LFN cache entry\r
- */\r
-char *FAT_int_GetLFN(tVFS_Node *node)\r
-{\r
-       t_lfncache      *tmp;\r
-       tmp = fat_lfncache;\r
-       while(tmp)\r
-       {\r
-               if(tmp->Inode == node->Inode && tmp->Impl == node->ImplInt)\r
-                       return tmp->Name;\r
-               tmp = tmp->Next;\r
-       }\r
-       tmp = malloc(sizeof(t_lfncache));\r
-       tmp->Inode = node->Inode;\r
-       tmp->Impl = node->ImplInt;\r
-       memset(tmp->Name, 0, 256);\r
-       \r
-       tmp->Next = fat_lfncache;\r
-       fat_lfncache = tmp;\r
-       \r
-       return tmp->Name;\r
-}\r
-\r
-/**\r
- \fn void FAT_int_DelLFN(tVFS_Node *node)\r
- \brief Delete a LFN cache entry\r
-*/\r
-void FAT_int_DelLFN(tVFS_Node *node)\r
-{\r
-       t_lfncache      *tmp;\r
-       \r
-       if(!fat_lfncache)       return;\r
-       \r
-       if(!fat_lfncache->Next)\r
-       {\r
-               tmp = fat_lfncache;\r
-               fat_lfncache = tmp->Next;\r
-               free(tmp);\r
-               return;\r
-       }\r
-       tmp = fat_lfncache;\r
-       while(tmp && tmp->Next)\r
-       {\r
-               if(tmp->Inode == node->Inode && tmp->Impl == node->ImplInt)\r
-               {\r
-                       free(tmp->Next);\r
-                       tmp->Next = tmp->Next->Next;\r
-                       return;\r
-               }\r
-               tmp = tmp->Next;\r
-       }\r
-}\r
-#endif\r
-\r
-/**\r
- \fn char *FAT_ReadDir(tVFS_Node *dirNode, int dirPos)\r
- \param dirNode        Node structure of directory\r
- \param dirPos Directory position\r
-**/\r
-char *FAT_ReadDir(tVFS_Node *dirNode, int dirpos)\r
-{\r
-       fat_filetable   fileinfo[16];   //Sizeof=32, 16 per sector\r
-        int    a=0;\r
-       tFAT_VolInfo    *disk = &gFAT_Disks[dirNode->ImplInt&7];\r
-       Uint32  cluster, offset;\r
-        int    preSkip;\r
-       char    *ret;\r
-       #if USE_LFN\r
-       char    *lfn = NULL;\r
-       #endif\r
-       \r
-       ENTER("pDirNode iDirPos", dirNode, dirpos);\r
-       \r
-       // Get Byte Offset and skip\r
-       offset = dirpos * sizeof(fat_filetable);\r
-       preSkip = offset / (512 * disk->bootsect.spc);\r
-       LOG("disk->bootsect.spc = %i", disk->bootsect.spc);\r
-       LOG("dirNode->size = %i", dirNode->Size);\r
-       cluster = dirNode->Inode;       // Cluster ID\r
-       \r
-       // Do Cluster Skip\r
-       // - Pre FAT32 had a reserved area for the root.\r
-       if( disk->type == FAT32 || cluster != disk->rootOffset )\r
-       {\r
-               //Skip previous clusters\r
-               for(a=preSkip;a--;)     {\r
-                       cluster = FAT_int_GetFatValue(disk, cluster);\r
-                       // Check for end of cluster chain\r
-                       if(cluster == -1) {     LEAVE('n');     return NULL;}\r
-               }\r
-       }\r
-       \r
-       // Bounds Checking (Used to spot heap overflows)\r
-       if(cluster > disk->clusterCount + 2)\r
-       {\r
-               Warning("FAT_ReadDir - Cluster ID is over cluster count (0x%x>0x%x)",\r
-                       cluster, disk->clusterCount+2);\r
-               LEAVE('n');\r
-               return NULL;\r
-       }\r
-       \r
-       LOG("cluster=0x%x, dirpos=%i", cluster, dirpos);\r
-       \r
-       // Compute Offsets\r
-       // - Pre FAT32 cluster base (in sectors)\r
-       if( cluster == disk->rootOffset && disk->type != FAT32 )\r
-               offset = disk->bootsect.resvSectCount + cluster*disk->bootsect.spc;\r
-       else\r
-       {       // FAT32 cluster base (in sectors)\r
-               offset = disk->firstDataSect;\r
-               offset += (cluster - 2) * disk->bootsect.spc;\r
-       }\r
-       // Sector in cluster\r
-       if(disk->bootsect.spc != 1)\r
-               offset += (dirpos / 16) % disk->bootsect.spc;\r
-       // Offset in sector\r
-       a = dirpos % 16;\r
-\r
-       LOG("offset=%i, a=%i", offset, a);\r
-       \r
-       // Read Sector\r
-       VFS_ReadAt(disk->fileHandle, offset*512, 512, fileinfo);        // Read Dir Data\r
-       \r
-       LOG("name[0] = 0x%x", (Uint8)fileinfo[a].name[0]);\r
-       //Check if this is the last entry\r
-       if( fileinfo[a].name[0] == '\0' ) {\r
-               dirNode->Size = dirpos;\r
-               LOG("End of list");\r
-               LEAVE('n');\r
-               return NULL;    // break\r
-       }\r
-       \r
-       // Check for empty entry\r
-       if( (Uint8)fileinfo[a].name[0] == 0xE5 ) {\r
-               LOG("Empty Entry");\r
-               LEAVE('p', VFS_SKIP);\r
-               return VFS_SKIP;        // Skip\r
-       }\r
-       \r
-       #if USE_LFN\r
-       // Get Long File Name Cache\r
-       lfn = FAT_int_GetLFN(dirNode);\r
-       if(fileinfo[a].attrib == ATTR_LFN)\r
-       {\r
-               fat_longfilename        *lfnInfo;\r
-                int    len;\r
-               \r
-               lfnInfo = (fat_longfilename *) &fileinfo[a];\r
-               if(lfnInfo->id & 0x40)  memset(lfn, 0, 256);\r
-               // Get the current length\r
-               len = strlen(lfn);\r
-               \r
-               // Sanity Check (FAT implementations should not allow >255 bytes)\r
-               if(len + 13 > 255)      return VFS_SKIP;\r
-               // Rebase all bytes\r
-               for(a=len+1;a--;)       lfn[a+13] = lfn[a];\r
-               \r
-               // Append new bytes\r
-               lfn[ 0] = lfnInfo->name1[0];    lfn[ 1] = lfnInfo->name1[1];\r
-               lfn[ 2] = lfnInfo->name1[2];    lfn[ 3] = lfnInfo->name1[3];\r
-               lfn[ 4] = lfnInfo->name1[4];    \r
-               lfn[ 5] = lfnInfo->name2[0];    lfn[ 6] = lfnInfo->name2[1];\r
-               lfn[ 7] = lfnInfo->name2[2];    lfn[ 8] = lfnInfo->name2[3];\r
-               lfn[ 9] = lfnInfo->name2[4];    lfn[10] = lfnInfo->name2[5];\r
-               lfn[11] = lfnInfo->name3[0];    lfn[12] = lfnInfo->name3[1];\r
-               LEAVE('p', VFS_SKIP);\r
-               return VFS_SKIP;\r
-       }\r
-       #endif\r
-       \r
-       //Check if it is a volume entry\r
-       if(fileinfo[a].attrib & 0x08) {\r
-               LEAVE('p', VFS_SKIP);\r
-               return VFS_SKIP;\r
-       }\r
-       // Ignore . and ..\r
-       if(fileinfo[a].name[0] == '.') {\r
-               LEAVE('p', VFS_SKIP);\r
-               return VFS_SKIP;\r
-       }       \r
-       \r
-       LOG("name='%c%c%c%c%c%c%c%c.%c%c%c'\n",\r
-               fileinfo[a].name[0], fileinfo[a].name[1], fileinfo[a].name[2], fileinfo[a].name[3],\r
-               fileinfo[a].name[4], fileinfo[a].name[5], fileinfo[a].name[6], fileinfo[a].name[7],\r
-               fileinfo[a].name[8], fileinfo[a].name[9], fileinfo[a].name[10] );\r
-       \r
-       #if USE_LFN\r
-       //node = FAT_int_CreateNode(dirNode, &fileinfo[a], lfn);\r
-       ret = FAT_int_CreateName(dirNode, &fileinfo[a], lfn);\r
-       lfn[0] = '\0';\r
-       #else\r
-       //node = FAT_int_CreateNode(dirNode, &fileinfo[a], NULL);\r
-       ret = FAT_int_CreateName(dirNode, &fileinfo[a], NULL);\r
-       #endif\r
-       \r
-       LEAVE('s', ret);\r
-       return ret;\r
-}\r
-\r
-/**\r
- * \fn tVFS_Node *FAT_FindDir(tVFS_Node *node, char *name)\r
- * \brief Finds an entry in the current directory\r
- */\r
-tVFS_Node *FAT_FindDir(tVFS_Node *node, char *name)\r
-{\r
-       fat_filetable   fileinfo[16];\r
-       char    tmpName[11];\r
-       #if USE_LFN\r
-       fat_longfilename        *lfnInfo;\r
-       char    *lfn = NULL;\r
-        int    lfnPos=255, lfnId = -1;\r
-       #endif\r
-        int    i=0;\r
-       tVFS_Node       *tmpNode;\r
-       Uint64  diskOffset;\r
-       tFAT_VolInfo    *disk = &gFAT_Disks[node->ImplInt];\r
-       Uint32  dirCluster;\r
-       Uint32  cluster;\r
-       \r
-       ENTER("pnode sname", node, name);\r
-       \r
-       // Fast Returns\r
-       if(!name || name[0] == '\0') {\r
-               LEAVE('n');\r
-               return NULL;\r
-       }\r
-       \r
-       #if USE_LFN\r
-       lfn = FAT_int_GetLFN(node);\r
-       #endif\r
-       \r
-       dirCluster = node->Inode;\r
-       // Seek to Directory\r
-       if( dirCluster == disk->rootOffset && disk->type != FAT32 )\r
-               diskOffset = (disk->bootsect.resvSectCount+dirCluster*disk->bootsect.spc) << 9;\r
-       else\r
-               diskOffset = (disk->firstDataSect+(dirCluster-2)*disk->bootsect.spc) << 9;\r
-       \r
-       for(;;i++)\r
-       {\r
-               // Load sector\r
-               if((i & 0xF) == 0) {\r
-                       //Log("FAT_FindDir: diskOffset = 0x%x", diskOffset);\r
-                       VFS_ReadAt(disk->fileHandle, diskOffset, 512, fileinfo);\r
-                       diskOffset += 512;\r
-               }\r
-               \r
-               //Check if the files are free\r
-               if(fileinfo[i&0xF].name[0] == '\0')     break;          //Free and last\r
-               if(fileinfo[i&0xF].name[0] == '\xE5')   goto loadCluster;       //Free\r
-               \r
-               \r
-               #if USE_LFN\r
-               // Long File Name Entry\r
-               if(fileinfo[i&0xF].attrib == ATTR_LFN)\r
-               {\r
-                       lfnInfo = (fat_longfilename *) &fileinfo[i&0xF];\r
-                       if(lfnInfo->id & 0x40) {\r
-                               memset(lfn, 0, 256);\r
-                               lfnPos = 255;\r
-                       }\r
-                       lfn[lfnPos--] = lfnInfo->name3[1];      lfn[lfnPos--] = lfnInfo->name3[0];\r
-                       lfn[lfnPos--] = lfnInfo->name2[5];      lfn[lfnPos--] = lfnInfo->name2[4];\r
-                       lfn[lfnPos--] = lfnInfo->name2[3];      lfn[lfnPos--] = lfnInfo->name2[2];\r
-                       lfn[lfnPos--] = lfnInfo->name2[1];      lfn[lfnPos--] = lfnInfo->name2[0];\r
-                       lfn[lfnPos--] = lfnInfo->name1[4];      lfn[lfnPos--] = lfnInfo->name1[3];\r
-                       lfn[lfnPos--] = lfnInfo->name1[2];      lfn[lfnPos--] = lfnInfo->name1[1];\r
-                       lfn[lfnPos--] = lfnInfo->name1[0];\r
-                       if((lfnInfo->id&0x3F) == 1)\r
-                       {\r
-                               memcpy(lfn, lfn+lfnPos+1, 256-lfnPos);\r
-                               lfnId = i+1;\r
-                       }\r
-               }\r
-               else\r
-               {\r
-                       // Remove LFN if it does not apply\r
-                       if(lfnId != i)  lfn[0] = '\0';\r
-               #endif\r
-                       // Get Real Filename\r
-                       FAT_int_ProperFilename(tmpName, fileinfo[i&0xF].name);\r
-               \r
-                       LOG("tmpName = '%s'", tmpName);\r
-               \r
-                       //Only Long name is case sensitive, 8.3 is not\r
-                       #if USE_LFN\r
-                       if(strucmp(tmpName, name) == 0 || strcmp(lfn, name) == 0) {\r
-                       #else\r
-                       if(strucmp(tmpName, name) == 0) {\r
-                       #endif\r
-                               cluster = fileinfo[i&0xF].cluster | (fileinfo[i&0xF].clusterHi << 16);\r
-                               tmpNode = Inode_GetCache(disk->inodeHandle, cluster);\r
-                               if(tmpNode == NULL)     // Node is not cached\r
-                               {\r
-                                       #if USE_LFN\r
-                                       tmpNode = FAT_int_CreateNode(node, &fileinfo[i&0xF], lfn);\r
-                                       #else\r
-                                       tmpNode = FAT_int_CreateNode(node, &fileinfo[i&0xF], NULL);\r
-                                       #endif\r
-                               }\r
-                               #if USE_LFN\r
-                               lfn[0] = '\0';\r
-                               #endif\r
-                               LEAVE('p', tmpNode);\r
-                               return tmpNode;\r
-                       }\r
-               #if USE_LFN\r
-               }\r
-               #endif\r
-               \r
-       loadCluster:\r
-               //Load Next cluster?\r
-               if( ((i+1) >> 4) % disk->bootsect.spc == 0 && ((i+1) & 0xF) == 0)\r
-               {\r
-                       if( dirCluster == disk->rootOffset && disk->type != FAT32 )\r
-                               continue;\r
-                       dirCluster = FAT_int_GetFatValue(disk, dirCluster);\r
-                       if(dirCluster == -1)    break;\r
-                       diskOffset = (disk->firstDataSect+(dirCluster-2)*disk->bootsect.spc)*512;\r
-               }\r
-       }\r
-       \r
-       LEAVE('n');\r
-       return NULL;\r
-}\r
-\r
-/**\r
- * \fn int FAT_Mknod(tVFS_Node *Node, char *Name, Uint Flags)\r
- * \brief Create a new node\r
- */\r
-int FAT_Mknod(tVFS_Node *Node, char *Name, Uint Flags)\r
-{\r
-       return 0;\r
-}\r
-\r
-/**\r
- * \fn int FAT_Relink(tVFS_Node *Node, char *OldName, char *NewName)\r
- * \brief Rename / Delete a file\r
- */\r
-int FAT_Relink(tVFS_Node *Node, char *OldName, char *NewName)\r
-{\r
-       return 0;\r
-}\r
-\r
-/**\r
- * \fn void FAT_CloseFile(tVFS_Node *Node)\r
- * \brief Close an open file\r
- */\r
-void FAT_CloseFile(tVFS_Node *Node)\r
-{\r
-       if(Node == NULL)        return ;\r
-       \r
-       Inode_UncacheNode(gFAT_Disks[Node->ImplInt].inodeHandle, Node->Inode);\r
-       #if USE_LFN\r
-       if(     !Inode_GetCache(gFAT_Disks[Node->ImplInt].inodeHandle, Node->Inode)\r
-       &&      Node->Flags & VFS_FFLAG_DIRECTORY)\r
-               FAT_int_DelLFN(Node);\r
-       else    // Get Cache references the node, so dereference it\r
-               Inode_UncacheNode(gFAT_Disks[Node->ImplInt].inodeHandle, Node->Inode);\r
-       #endif\r
-       return ;\r
-}\r
-\r
-/**\r
- * \fn void fat_install()\r
- * \brief Add the FAT Filesystem to the VFS\r
- */\r
-void fat_install()\r
-{\r
-       VFS_AddDriver( &gFAT_FSInfo );\r
-}\r
diff --git a/Kernel/vfs/fs/fs_fat.h b/Kernel/vfs/fs/fs_fat.h
deleted file mode 100644 (file)
index a4f7f7b..0000000
+++ /dev/null
@@ -1,167 +0,0 @@
-/*\r
- * Acess2\r
- * FAT12/16/32 Driver\r
- * vfs/fs/fs_fat.h\r
- */\r
-#ifndef _FS_FAT_H_\r
-#define _FS_FAT_H_\r
-\r
-// === On Disk Structures ===\r
-/**\r
- * \struct fat_bootsect_s\r
- * \brief Bootsector format\r
- */\r
-struct fat_bootsect_s\r
-{\r
-       Uint8   jmp[3]; //!< Jump Instruction\r
-       char    oemname[8];     //!< OEM Name. Typically MSDOS1.1\r
-       Uint16  bps;    //!< Bytes per Sector. Assumed to be 512\r
-       Uint8   spc;            //!< Sectors per Cluster\r
-       Uint16  resvSectCount;  //!< Number of reserved sectors at beginning of volume\r
-       Uint8   fatCount;       //!< Number of copies of the FAT\r
-       Uint16  files_in_root;  //!< Count of files in the root directory\r
-       Uint16  totalSect16;    //!< Total sector count (FAT12/16)\r
-       Uint8   mediaDesc;      //!< Media Desctiptor\r
-       Uint16  fatSz16;        //!< FAT Size (FAT12/16)\r
-       Uint16  spt;    //!< Sectors per track. Ignored (Acess uses LBA)\r
-       Uint16  heads;  //!< Heads. Ignored (Acess uses LBA)\r
-       Uint32  hiddenCount;    //!< ???\r
-       Uint32  totalSect32;    //!< Total sector count (FAT32)\r
-       union {\r
-               struct {\r
-                       Uint8   drvNum; //!< Drive Number. BIOS Drive ID (E.g. 0x80)\r
-                       Uint8   resv;   //!< Reserved byte\r
-                       Uint8   bootSig;        //!< Boot Signature. ???\r
-                       Uint32  volId;  //!< Volume ID\r
-                       char    label[11];      //!< Disk Label\r
-                       char    fsType[8];      //!< FS Type. ???\r
-               } __attribute__((packed)) fat16;        //!< FAT16 Specific information\r
-               struct {\r
-                       Uint32  fatSz32;        //!< 32-Bit FAT Size\r
-                       Uint16  extFlags;       //!< Extended flags\r
-                       Uint16  fsVer;  //!< Filesystem Version\r
-                       Uint32  rootClust;      //!< Root Cluster ID\r
-                       Uint16  fsInfo; //!< FS Info. ???\r
-                       Uint16  backupBS;       //!< Backup Bootsector Sector Offset\r
-                       char    resv[12];       //!< Reserved Data\r
-                       Uint8   drvNum; //!< Drive Number\r
-                       char    resv2;  //!< Reserved Data\r
-                       Uint8   bootSig;        //!< Boot Signature. ???\r
-                       Uint32  volId;  //!< Volume ID\r
-                       char    label[11];      //!< Disk Label\r
-                       char    fsType[8];      //!< Filesystem Type. ???\r
-               } __attribute__((packed)) fat32;        //!< FAT32 Specific Information\r
-       }__attribute__((packed)) spec;  //!< Non Shared Data\r
-       char pad[512-90];       //!< Bootsector Data (Code/Boot Signature 0xAA55)\r
-} __attribute__((packed));\r
-\r
-/**\r
- \struct fat_filetable_s\r
- \brief Format of a 8.3 file entry on disk\r
-*/\r
-struct fat_filetable_s {\r
-       char    name[11];       //!< 8.3 Name\r
-       Uint8   attrib; //!< File Attributes.\r
-       Uint8   ntres;  //!< Reserved for NT - Set to 0\r
-       Uint8   ctimems;        //!< 10ths of a second ranging from 0-199 (2 seconds)\r
-       Uint16  ctime;  //!< Creation Time\r
-       Uint16  cdate;  //!< Creation Date\r
-       Uint16  adate;  //!< Accessed Data. No Time feild though\r
-       Uint16  clusterHi;      //!< High Cluster. 0 for FAT12 and FAT16\r
-       Uint16  mtime;  //!< Last Modified Time\r
-       Uint16  mdate;  //!< Last Modified Date\r
-       Uint16  cluster;        //!< Low Word of First cluster\r
-       Uint32  size;   //!< Size of file\r
-} __attribute__((packed));\r
-\r
-/**\r
- \struct fat_longfilename_s\r
- \brief Format of a long file name entry on disk\r
-*/\r
-struct fat_longfilename_s {\r
-       Uint8   id;     //!< ID of entry. Bit 6 is set for last entry\r
-       Uint16  name1[5];       //!< 5 characters of name\r
-       Uint8   attrib; //!< Attributes. Must be ATTR_LFN\r
-       Uint8   type;   //!< Type. ???\r
-       Uint8   checksum;       //!< Checksum\r
-       Uint16  name2[6];       //!< 6 characters of name\r
-       Uint16  firstCluster;   //!< Used for non LFN compatability. Set to 0\r
-       Uint16  name3[2];       //!< Last 2 characters of name\r
-} __attribute__((packed));\r
-\r
-/**\r
- * \name File Attributes\r
- * \brief Flag values for ::fat_filetable_s.attrib\r
- * \{\r
- */\r
-#define ATTR_READONLY  0x01    //!< Read-only file\r
-#define ATTR_HIDDEN            0x02    //!< Hidden File\r
-#define ATTR_SYSTEM            0x04    //!< System File\r
-#define ATTR_VOLUMEID  0x08    //!< Volume ID (Deprecated)\r
-#define ATTR_DIRECTORY 0x10    //!< Directory\r
-/**\r
- * \brief File needs archiving\r
- * \note User set flag, no significance to the FS driver\r
- */\r
-#define ATTR_ARCHIVE   0x20\r
-/**\r
- * \brief Meta Attribute \r
- * \r
- * If ::fat_filetable_s.attrib equals ATTR_LFN the file is a LFN entry\r
- */\r
-#define        ATTR_LFN                (ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUMEID)\r
-/**\r
- * \}\r
- */\r
-\r
-/**\r
- * \brief Internal IDs for FAT types\r
- */\r
-enum eFatType\r
-{\r
-       FAT12,  //!< FAT12 Volume\r
-       FAT16,  //!< FAT16 Volume\r
-       FAT32,  //!< FAT32 Volume\r
-};\r
-\r
-/**\r
- * \name End of Cluster marks\r
- * \brief FAT values that indicate the end of a cluster chain in\r
- *        different versions.\r
- * \{\r
- */\r
-#define        EOC_FAT12       0x0FFF  //!< FAT-12 Mark\r
-#define        EOC_FAT16       0xFFFF  //!< FAT-16 Mark\r
-#define        EOC_FAT32       0x0FFFFFF       //!< FAT-32 Mark\r
-/**\r
- * \}\r
- */\r
-\r
-typedef struct fat_bootsect_s fat_bootsect;\r
-typedef struct fat_filetable_s fat_filetable;\r
-typedef struct fat_longfilename_s fat_longfilename;\r
-\r
-// === Memory Structures ===\r
-/**\r
- * \struct drv_fat_volinfo_s\r
- * \brief Representation of a volume in memory\r
- */\r
-struct drv_fat_volinfo_s\r
-{\r
-        int    fileHandle;     //!< File Handle\r
-        int    type;   //!< FAT Type. See eFatType\r
-       char    name[12];       //!< Volume Name (With NULL Terminator)\r
-       Uint32  firstDataSect;  //!< First data sector\r
-       Uint32  rootOffset;     //!< Root Offset (clusters)\r
-       Uint32  clusterCount;   //!< Total Cluster Count\r
-       fat_bootsect    bootsect;       //!< Boot Sector\r
-       tVFS_Node       rootNode;       //!< Root Node\r
-        int            inodeHandle;    //!< Inode Cache Handle\r
-       #if CACHE_FAT\r
-       Uint32  *FATCache;      //!< FAT Cache\r
-       #endif\r
-};\r
-\r
-typedef struct drv_fat_volinfo_s tFAT_VolInfo;\r
-\r
-#endif\r
index c8636b1..45e20d9 100644 (file)
@@ -20,6 +20,9 @@ tVFS_Driver   *VFS_GetFSByName(char *Name);
  int   VFS_AddDriver(tVFS_Driver *Info);
 void   VFS_UpdateDriverFile();
 
+// === EXPORTS ===
+EXPORT(VFS_AddDriver);
+
 // === GLOBALS ===
 tVFS_Node      NULLNode = {0};
 tSpinlock      siDriverListLock = 0;
@@ -81,13 +84,11 @@ char *VFS_GetTruePath(char *Path)
  */
 void VFS_GetMemPath(char *Dest, void *Base, Uint Length)
 {
-       Log("VFS_GetMemPath: (Base=%p, Length=0x%x, Dest=%p)", Base, Length, Dest);
        Dest[0] = '$';
        itoa( &Dest[1], (Uint)Base, 16, BITS/4, '0' );
        Dest[BITS/4+1] = ':';
        itoa( &Dest[BITS/4+2], Length, 16, BITS/4, '0' );
-       
-       Log("VFS_GetMemPath: Dest = \"%s\"", Dest);
+       Dest[BITS/2+2] = '\0';
 }
 
 /**
index 4120b20..3c75671 100644 (file)
@@ -60,8 +60,6 @@ tVFS_Node *VFS_MemFile_Create(tVFS_Node *Unused, char *Path)
        // Check for NULL byte
        if(*str != '\0')        return NULL;
        
-       Log(" VFS_MemFile_Create: base=0x%x, size=0x%x", base, size);
-       
        // Allocate and fill node
        ret = malloc(sizeof(tVFS_Node));
        memset(ret, 0, sizeof(tVFS_Node));
index 090d024..45591a4 100644 (file)
@@ -43,7 +43,7 @@ int VFS_Mount(char *Device, char *MountPoint, char *Filesystem, char *Options)
        // Get the filesystem
        fs = VFS_GetFSByName(Filesystem);
        if(!fs) {
-               Warning("VFS_Mount - Unknown FS Type '%s'", Filesystem);
+               Log_Warning("VFS", "VFS_Mount - Unknown FS Type '%s'", Filesystem);
                return -1;
        }
        
@@ -96,7 +96,7 @@ int VFS_Mount(char *Device, char *MountPoint, char *Filesystem, char *Options)
        }
        RELEASE( &glVFS_MountList );
        
-       Log("VFS_Mount: Mounted '%s' to '%s' ('%s')", Device, MountPoint, Filesystem);
+       Log_Log("VFS", "Mounted '%s' to '%s' ('%s')", Device, MountPoint, Filesystem);
        
        VFS_UpdateMountFile();
        
index 0124e62..a898d5d 100644 (file)
@@ -121,9 +121,9 @@ void Inode_UncacheNode(int Handle, Uint64 Inode)
        tCachedInode    *ent, *prev;
        
        cache = Inode_int_GetFSCache(Handle);
-       if(!cache)      return;
+       if(!cache)      return ;
        
-       if(Inode > cache->MaxCached)    return;
+       if(Inode > cache->MaxCached)    return ;
        
        // Search Cache
        ent = cache->FirstNode;
@@ -147,8 +147,10 @@ void Inode_UncacheNode(int Handle, Uint64 Inode)
                                
                        free(ent);
                }
-               return;
+               return ;
        }
+       
+       return ;
 }
 
 /**
index 9023afe..ba53f12 100644 (file)
--- a/Makefile
+++ b/Makefile
 SUBMAKE = $(MAKE) --no-print-directory
 
 MODULES += $(DYNMODS)
-USRLIBS = crt0.o acess.ld ld-acess.so libacess.so libgcc.so libc.so
-USRAPPS = init login CLIShell cat ls mount ifconfig
+USRLIBS := crt0.o acess.ld ld-acess.so libacess.so libgcc.so libc.so
+USRAPPS := init login CLIShell cat ls mount ifconfig
 
-ALL_MODULES = $(addprefix all-,$(MODULES))
-ALL_USRLIBS = $(addprefix all-,$(USRLIBS))
-ALL_USRAPPS = $(addprefix all-,$(USRAPPS))
-CLEAN_MODULES = $(addprefix clean-,$(MODULES))
-CLEAN_USRLIBS = $(addprefix clean-,$(USRLIBS))
-CLEAN_USRAPPS = $(addprefix clean-,$(USRAPPS))
-INSTALL_MODULES = $(addprefix install-,$(MODULES))
-INSTALL_USRLIBS = $(addprefix install-,$(USRLIBS))
-INSTALL_USRAPPS = $(addprefix install-,$(USRAPPS))
-ALLINSTALL_MODULES = $(addprefix allinstall-,$(MODULES))
-ALLINSTALL_USRLIBS = $(addprefix allinstall-,$(USRLIBS))
-ALLINSTALL_USRAPPS = $(addprefix allinstall-,$(USRAPPS))
+#ALL_DYNMODS = $(addprefix all-,$(DYNMODS))
+ALL_MODULES := $(addprefix all-,$(MODULES))
+ALL_USRLIBS := $(addprefix all-,$(USRLIBS))
+ALL_USRAPPS := $(addprefix all-,$(USRAPPS))
+CLEAN_MODULES := $(addprefix clean-,$(MODULES))
+CLEAN_USRLIBS := $(addprefix clean-,$(USRLIBS))
+CLEAN_USRAPPS := $(addprefix clean-,$(USRAPPS))
+INSTALL_MODULES := $(addprefix install-,$(MODULES))
+INSTALL_USRLIBS := $(addprefix install-,$(USRLIBS))
+INSTALL_USRAPPS := $(addprefix install-,$(USRAPPS))
+AI_DYNMODS := $(addprefix allinstall-,$(DYNMODS))
+AI_MODULES := $(addprefix allinstall-,$(MODULES))
+AI_USRLIBS := $(addprefix allinstall-,$(USRLIBS))
+AI_USRAPPS := $(addprefix allinstall-,$(USRAPPS))
 
 .PHONY: all clean install \
        $(ALL_MODULES) all-Kernel $(ALL_USRLIBS) $(ALL_USRAPPS) \
-       $(ALLINSTALL_MODULES) allinstall-Kernel $(ALLINSTALL_USRLIBS) $(ALLINSTALL_USRAPPS) \
+       $(AI_MODULES) allinstall-Kernel $(AI_USRLIBS) $(AI_USRAPPS) \
        $(CLEAN_MODULES) clean-Kernel $(CLEAN_USRLIBS) $(CLEAN_USRAPPS) \
        $(INSTALL_MODULES) install-Kernel $(INSTALL_USRLIBS) $(INSTALL_USRAPPS)
 
-kmode: $(ALLINSTALL_MODULES) allinstall-Kernel
+kmode: $(AI_MODULES) $(AI_DYNMODS) allinstall-Kernel
 
-all:   $(ALL_MODULES) all-Kernel $(ALL_USRLIBS) $(ALL_USRAPPS)
-all-install:   $(ALLINSTALL_MODULES) allinstall-Kernel $(ALLINSTALL_USRLIBS) $(ALLINSTALL_USRAPPS)
-clean: $(CLEAN_MODULES) clean-Kernel $(CLEAN_USRLIBS) $(CLEAN_USRAPPS)
-install:       $(INSTALL_MODULES) install-Kernel $(INSTALL_USRLIBS) $(INSTALL_USRAPPS)
+all:   $(ALL_DYNMODS) $(ALL_MODULES) all-Kernel $(ALL_USRLIBS) $(ALL_USRAPPS)
+all-install:   $(AI_DYNMODS) $(AI_MODULES) allinstall-Kernel $(AI_USRLIBS) $(AI_USRAPPS)
+clean: $(CLEAN_DYNMODS) $(CLEAN_MODULES) clean-Kernel $(CLEAN_USRLIBS) $(CLEAN_USRAPPS)
+install:       $(INSTALL_DYNMODS) $(INSTALL_MODULES) install-Kernel $(INSTALL_USRLIBS) $(INSTALL_USRAPPS)
 
 # Compile Only
 $(ALL_MODULES): all-%:
@@ -51,13 +53,15 @@ $(ALL_USRAPPS): all-%:
        @echo === User Application: $* && $(SUBMAKE) all -C Usermode/Applications/$*_src
 
 # Compile & Install
-$(ALLINSTALL_MODULES): allinstall-%:
+#$(AI_DYNMODS): allinstall-%:
+#      @echo === Dynamic Module: $* && STATIC_MODULE=yes $(SUBMAKE) all install -C Modules/$*
+$(AI_MODULES): allinstall-%:
        @echo === Module: $* && $(SUBMAKE) all install -C Modules/$*
 allinstall-Kernel:
        @echo === Kernel && $(SUBMAKE) all install -C Kernel
-$(ALLINSTALL_USRLIBS): allinstall-%:
+$(AI_USRLIBS): allinstall-%:
        @echo === User Library: $* && $(SUBMAKE) all install -C Usermode/Libraries/$*_src
-$(ALLINSTALL_USRAPPS): allinstall-%:
+$(AI_USRAPPS): allinstall-%:
        @echo === User Application: $* && $(SUBMAKE) all install -C Usermode/Applications/$*_src
 
 # Clean up compilation
index 5abb96d..ecf32ac 100644 (file)
@@ -24,14 +24,16 @@ ifeq ($(ARCHDIR),)
        ARCHDIR = x86
 endif
 
-FILESYSTEMS = fat
+FILESYSTEMS = 
 DRIVERS = 
 MODULES  = Storage/ATA Storage/FDD
 MODULES += Network/NE2000
-MODULES += Display/BochsGA
-MODULES += Filesystems/FS_Ext2
+MODULES += Display/VESA
+#MODULES += Display/BochsGA
+MODULES += Filesystems/Ext2
+MODULES += Filesystems/FAT
 MODULES += IPStack
-DYNMODS = USB Interfaces/UDI
+DYNMODS = USB/Core Interfaces/UDI
 
 #DISTROOT = /mnt/AcessHDD/Acess2
 #DISTROOT = ~/Projects/Acess2/Filesystem
index 06d362c..8f73ccb 100644 (file)
@@ -1,7 +1,6 @@
 /**\r
  * \file drv_bochsvbe.c\r
- * \brief BGA (Bochs Graphic Adapter) Driver\r
- * \note for Acess2\r
+ * \brief BGA (Bochs Graphic Adapter) Driver for Acess2\r
  * \warning This driver does NOT support the Bochs PCI VGA driver\r
 */\r
 #define DEBUG  0\r
 \r
 #define INT\r
 \r
-// === TYPEDEFS ===\r
-typedef struct {\r
+// === TYPES ===\r
+typedef struct sBGA_Mode {\r
        Uint16  width;\r
        Uint16  height;\r
        Uint16  bpp;\r
-       Uint16  flags;\r
        Uint32  fbSize;\r
-} t_bga_mode;\r
+}      tBGA_Mode;\r
 \r
 // === CONSTANTS ===\r
-enum eMode_Flags {\r
-       MODEFLAG_TEXT = 1\r
-};\r
 #define        BGA_LFB_MAXSIZE (1024*768*4)\r
 #define        VBE_DISPI_BANK_ADDRESS  0xA0000\r
 #define VBE_DISPI_LFB_PHYSICAL_ADDRESS 0xE0000000\r
@@ -70,7 +65,7 @@ Uint64        BGA_Write(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer);
  int   BGA_Ioctl(tVFS_Node *node, int id, void *data);\r
 \r
 // === GLOBALS ===\r
-MODULE_DEFINE(0, 0x0032, BochsGA, BGA_Install, NULL, NULL);\r
+MODULE_DEFINE(0, 0x0032, BochsGA, BGA_Install, NULL, "PCI", NULL);\r
 tDevFS_Driver  gBGA_DriverStruct = {\r
        NULL, "BochsGA",\r
        {\r
@@ -80,17 +75,15 @@ tDevFS_Driver       gBGA_DriverStruct = {
        }\r
 };\r
  int   giBGA_CurrentMode = -1;\r
+ int   giBGA_BufferFormat = 0;\r
 tVideo_IOCtl_Pos       gBGA_CursorPos = {-1,-1};\r
- int   giBGA_DriverId = -1;\r
 Uint   *gBGA_Framebuffer;\r
-t_bga_mode     gBGA_Modes[] = {\r
+tBGA_Mode      gpBGA_CurrentMode;\r
+const tBGA_Mode        gBGA_Modes[] = {\r
        {},\r
-       { 80,25, 12, MODEFLAG_TEXT, 80*25*8},   // 640 x 480\r
-       {100,37, 12, MODEFLAG_TEXT, 100*37*8},  // 800 x 600\r
-       {640,480,8, 0, 640*480},\r
        {640,480,32, 0, 640*480*4},\r
-       {800,600,8, 0, 800*600},\r
        {800,600,32, 0, 800*600*4},\r
+       {1024,768,32, 0, 1024*768*4}\r
 };\r
 #define        BGA_MODE_COUNT  (sizeof(gBGA_Modes)/sizeof(gBGA_Modes[0]))\r
 \r
@@ -100,27 +93,27 @@ t_bga_mode gBGA_Modes[] = {
  */\r
 int BGA_Install(char **Arguments)\r
 {\r
-        int    bga_version = 0;\r
+        int    version = 0;\r
        \r
        // Check BGA Version\r
-       bga_version = BGA_int_ReadRegister(VBE_DISPI_INDEX_ID);\r
+       version = BGA_int_ReadRegister(VBE_DISPI_INDEX_ID);\r
+       \r
        // NOTE: This driver was written for 0xB0C4, but they seem to be backwards compatable\r
-       if(bga_version < 0xB0C4 || bga_version > 0xB0C5) {\r
-               Warning("[BGA ] Bochs Adapter Version is not 0xB0C4 or 0xB0C5, instead 0x%x", bga_version);\r
-               return 0;\r
+       if(version < 0xB0C4 || version > 0xB0C5) {\r
+               Log_Warning("BGA", "Bochs Adapter Version is not 0xB0C4 or 0xB0C5, instead 0x%x", version);\r
+               return MODULE_ERR_NOTNEEDED;\r
        }\r
        \r
        // Install Device\r
-       giBGA_DriverId = DevFS_AddDevice( &gBGA_DriverStruct );\r
-       if(giBGA_DriverId == -1) {\r
-               Warning("[BGA ] Unable to register with DevFS, maybe already loaded?");\r
-               return 0;\r
+       if(DevFS_AddDevice( &gBGA_DriverStruct ) == -1) {\r
+               Log_Warning("BGA", "Unable to register with DevFS, maybe already loaded?");\r
+               return MODULE_ERR_MISC;\r
        }\r
        \r
        // Map Framebuffer to hardware address\r
        gBGA_Framebuffer = (void *) MM_MapHWPage(VBE_DISPI_LFB_PHYSICAL_ADDRESS, 768);  // 768 pages (3Mb)\r
        \r
-       return 1;\r
+       return MODULE_ERR_OK;\r
 }\r
 \r
 /**\r
@@ -128,7 +121,7 @@ int BGA_Install(char **Arguments)
  */\r
 void BGA_Uninstall()\r
 {\r
-       //DevFS_DelDevice( giBGA_DriverId );\r
+       DevFS_DelDevice( &gBGA_DriverStruct );\r
        MM_UnmapHWPage( VBE_DISPI_LFB_PHYSICAL_ADDRESS, 768 );\r
 }\r
 \r
@@ -142,7 +135,7 @@ Uint64 BGA_Read(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer)
        if(giBGA_CurrentMode == -1)     return -1;\r
        \r
        // Check Offset and Length against Framebuffer Size\r
-       if(off+len > gBGA_Modes[giBGA_CurrentMode].fbSize)\r
+       if(off+len > gpBGA_CurrentMode->fbSize)\r
                return -1;\r
        \r
        // Copy from Framebuffer\r
@@ -164,24 +157,27 @@ Uint64 BGA_Write(tVFS_Node *node, Uint64 off, Uint64 len, void *Buffer)
                return -1;\r
        }\r
        \r
-       // Check Input against Frambuffer Size\r
-       if(off + len > gBGA_Modes[giBGA_CurrentMode].fbSize) {\r
-               LEAVE('i', -1);\r
-               return -1;\r
-       }\r
-       \r
        // Text Mode\r
-       if( gBGA_Modes[giBGA_CurrentMode].flags & MODEFLAG_TEXT )\r
+       switch( giBGA_BufferFormat )\r
        {\r
+       case VIDEO_BUFFMT_TEXT:\r
+               {\r
                tVT_Char        *chars = Buffer;\r
-                int    pitch = gBGA_Modes[giBGA_CurrentMode].width * giVT_CharWidth;\r
+                int    pitch = gpBGA_CurrentMode->width * giVT_CharWidth;\r
                 int    x, y;\r
                Uint32  *dest;\r
                \r
                off /= sizeof(tVT_Char);\r
                dest = (void*)gBGA_Framebuffer;\r
-               x = (off % gBGA_Modes[giBGA_CurrentMode].width) * giVT_CharWidth;\r
-               y = (off / gBGA_Modes[giBGA_CurrentMode].width) * giVT_CharHeight;\r
+               x = (off % gpBGA_CurrentMode->width) * giVT_CharWidth;\r
+               y = (off / gpBGA_CurrentMode->width) * giVT_CharHeight;\r
+               \r
+               // Sanity Check\r
+               if(y > gpBGA_CurrentMode->height) {\r
+                       LEAVE('i', 0);\r
+                       return 0;\r
+               }\r
+               \r
                dest += y * pitch;\r
                dest += x * giVT_CharWidth;\r
                len /= sizeof(tVT_Char);\r
@@ -204,20 +200,31 @@ Uint64 BGA_Write(tVFS_Node *node, Uint64 off, Uint64 len, void *Buffer)
                                dest += pitch*(giVT_CharHeight-1);\r
                        }\r
                }\r
-       }\r
-       else\r
-       {\r
+               }\r
+               break;\r
+       \r
+       case VIDEO_BUFFMT_FRAMEBUFFER:\r
+               {\r
                Uint8   *destBuf = (Uint8*) ((Uint)gBGA_Framebuffer + (Uint)off);\r
                \r
-               Log("buffer = %p", Buffer);\r
-               Log("Updating Framebuffer (%p to %p)",\r
-                       destBuf, destBuf + (Uint)len);\r
+               if( off + len > gpBGA_CurrentMode->fbSize ) {\r
+                       LEAVE('i', 0);\r
+                       return 0;\r
+               }\r
+               \r
+               LOG("buffer = %p", Buffer);\r
+               LOG("Updating Framebuffer (%p to %p)", destBuf, destBuf + (Uint)len);\r
                \r
                \r
                // Copy to Frambuffer\r
                memcpy(destBuf, Buffer, len);\r
                \r
-               Log("BGA Framebuffer updated");\r
+               LOG("BGA Framebuffer updated");\r
+               }\r
+               break;\r
+       default:\r
+               LEAVE('i', -1);\r
+               return -1;\r
        }\r
        \r
        LEAVE('i', len);\r
@@ -225,13 +232,13 @@ Uint64 BGA_Write(tVFS_Node *node, Uint64 off, Uint64 len, void *Buffer)
 }\r
 \r
 /**\r
- * \fn INT int BGA_Ioctl(tVFS_Node *node, int ID, void *Data)\r
+ * \fn int BGA_Ioctl(tVFS_Node *Node, int ID, void *Data)\r
  * \brief Handle messages to the device\r
  */\r
-INT int BGA_Ioctl(tVFS_Node *node, int ID, void *Data)\r
+int BGA_Ioctl(tVFS_Node *Node, int ID, void *Data)\r
 {\r
         int    ret = -2;\r
-       ENTER("pNode iId pData", node, ID, Data);\r
+       ENTER("pNode iId pData", Node, ID, Data);\r
        \r
        switch(ID)\r
        {\r
@@ -264,9 +271,10 @@ INT int BGA_Ioctl(tVFS_Node *node, int ID, void *Data)
                ret = BGA_int_ModeInfo((tVideo_IOCtl_Mode*)Data);\r
                break;\r
        \r
-       // Request Access to LFB\r
-       case VIDEO_IOCTL_REQLFB:\r
-               ret = BGA_int_MapFB( *(void**)Data );\r
+       case VIDEO_IOCTL_SETBUFFORMAT:\r
+               ret = giBGA_BufferFormat;\r
+               if(Data)\r
+                       giBGA_BufferFormat = *(int*)Data;\r
                break;\r
        \r
        case VIDEO_IOCTL_SETCURSOR:\r
@@ -274,6 +282,11 @@ INT int BGA_Ioctl(tVFS_Node *node, int ID, void *Data)
                gBGA_CursorPos.y = ((tVideo_IOCtl_Pos*)Data)->y;\r
                break;\r
        \r
+       // Request Access to LFB\r
+       case VIDEO_IOCTL_REQLFB:\r
+               ret = BGA_int_MapFB( *(void**)Data );\r
+               break;\r
+       \r
        default:\r
                LEAVE('i', -2);\r
                return -2;\r
@@ -294,14 +307,14 @@ void BGA_int_WriteRegister(Uint16 reg, Uint16 value)
        outw(VBE_DISPI_IOPORT_DATA, value);\r
 }\r
 \r
-INT Uint16 BGA_int_ReadRegister(Uint16 reg)\r
+Uint16 BGA_int_ReadRegister(Uint16 reg)\r
 {\r
        outw(VBE_DISPI_IOPORT_INDEX, reg);\r
        return inw(VBE_DISPI_IOPORT_DATA);\r
 }\r
 \r
 #if 0\r
-INT void BGA_int_SetBank(Uint16 bank)\r
+void BGA_int_SetBank(Uint16 bank)\r
 {\r
        BGA_int_WriteRegister(VBE_DISPI_INDEX_BANK, bank);\r
 }\r
@@ -311,15 +324,14 @@ INT void BGA_int_SetBank(Uint16 bank)
  * \fn void BGA_int_SetMode(Uint16 width, Uint16 height, Uint16 bpp)\r
  * \brief Sets the video mode from the dimensions and bpp given\r
  */\r
-void BGA_int_SetMode(Uint16 width, Uint16 height)\r
+void BGA_int_SetMode(Uint16 Width, Uint16 Height)\r
 {\r
-       ENTER("iwidth iheight ibpp", width, height, bpp);\r
+       ENTER("iWidth iheight ibpp", Width, Height, bpp);\r
        BGA_int_WriteRegister(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_DISABLED);\r
-    BGA_int_WriteRegister(VBE_DISPI_INDEX_XRES,        width);\r
-    BGA_int_WriteRegister(VBE_DISPI_INDEX_YRES,        height);\r
+    BGA_int_WriteRegister(VBE_DISPI_INDEX_XRES,        Width);\r
+    BGA_int_WriteRegister(VBE_DISPI_INDEX_YRES,        Height);\r
     BGA_int_WriteRegister(VBE_DISPI_INDEX_BPP, 32);\r
     BGA_int_WriteRegister(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED | VBE_DISPI_NOCLEARMEM | VBE_DISPI_LFB_ENABLED);\r
-    //BGA_int_WriteRegister(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED | VBE_DISPI_NOCLEARMEM);\r
        LEAVE('-');\r
 }\r
 \r
@@ -343,6 +355,7 @@ int BGA_int_UpdateMode(int id)
                        gBGA_Modes[id].height);\r
        \r
        giBGA_CurrentMode = id;\r
+       gpBGA_CurrentMode = &gBGA_Modes[id];\r
        return id;\r
 }\r
 \r
@@ -447,10 +460,10 @@ int BGA_int_MapFB(void *Dest)
        \r
        // Sanity Check\r
        if((Uint)Dest > 0xC0000000)     return 0;\r
-       if(gBGA_Modes[giBGA_CurrentMode].bpp < 15)      return 0;       // Only non-pallete modes are supported\r
+       if(gpBGA_CurrentMode->bpp < 15) return 0;       // Only non-pallete modes are supported\r
        \r
        // Count required pages\r
-       pages = (gBGA_Modes[giBGA_CurrentMode].fbSize + 0xFFF) >> 12;\r
+       pages = (gpBGA_CurrentMode->fbSize + 0xFFF) >> 12;\r
        \r
        // Check if there is space\r
        for( i = 0; i < pages; i++ )\r
index 80c6d4d..b543160 100644 (file)
@@ -1 +1,3 @@
+CATEGORY = Video
+
 -include ../../Makefile.tpl
diff --git a/Modules/Display/VESA/Makefile b/Modules/Display/VESA/Makefile
new file mode 100644 (file)
index 0000000..d8da233
--- /dev/null
@@ -0,0 +1,7 @@
+#
+#
+
+OBJ = main.o
+NAME = VESA
+
+-include ../Makefile.tpl
diff --git a/Modules/Display/VESA/common.h b/Modules/Display/VESA/common.h
new file mode 100644 (file)
index 0000000..eeaddd5
--- /dev/null
@@ -0,0 +1,59 @@
+/**
+ */
+#ifndef _COMMON_H_
+#define _COMMON_H_
+
+// === TYPES ===
+typedef struct sFarPtr
+{
+       Uint16  ofs;
+       Uint16  seg;
+}      tFarPtr;
+
+typedef struct sVesa_Mode
+{
+       Uint16  code;
+       Uint16  width, height;
+       Uint16  pitch, bpp;
+       Uint16  flags;
+       Uint32  fbSize;
+       Uint32  framebuffer;
+}      tVesa_Mode;
+
+typedef struct sVesa_CallModeInfo
+{
+       Uint16  attributes;
+       Uint8   winA,winB;
+       Uint16  granularity;
+       Uint16  winsize;
+       Uint16  segmentA, segmentB;
+       tFarPtr realFctPtr;
+       Uint16  pitch;  // Bytes per scanline
+
+       Uint16  Xres, Yres;
+       Uint8   Wchar, Ychar, planes, bpp, banks;
+       Uint8   memory_model, bank_size, image_pages;
+       Uint8   reserved0;
+
+       Uint8   red_mask, red_position;
+       Uint8   green_mask, green_position;
+       Uint8   blue_mask, blue_position;
+       Uint8   rsv_mask, rsv_position;
+       Uint8   directcolor_attributes;
+
+       Uint32  physbase;  // Your LFB address ;)
+       Uint32  reserved1;
+       Sint16  reserved2;
+}      tVesa_CallModeInfo;
+
+typedef struct sVesa_CallInfo
+{
+   char                signature[4];           // == "VESA"
+   Uint16      Version;        // == 0x0300 for Vesa 3.0
+   tFarPtr     OEMString;      // isa vbeFarPtr
+   Uint8       Capabilities[4];        
+   tFarPtr     VideoModes;     // isa vbeParPtr
+   Uint16      TotalMemory;    // as # of 64KB blocks
+}      tVesa_CallInfo;
+
+#endif
diff --git a/Modules/Display/VESA/main.c b/Modules/Display/VESA/main.c
new file mode 100644 (file)
index 0000000..e87ca05
--- /dev/null
@@ -0,0 +1,403 @@
+/*\r
+ * AcessOS 1\r
+ * Video BIOS Extensions (Vesa) Driver\r
+ */\r
+#define DEBUG  1\r
+#define VERSION        0x100\r
+\r
+#include <acess.h>\r
+#include <vfs.h>\r
+#include <tpl_drv_video.h>\r
+#include <fs_devfs.h>\r
+#include <modules.h>\r
+#include <vm8086.h>\r
+#include "common.h"\r
+\r
+// === CONSTANTS ===\r
+#define        FLAG_LFB        0x1\r
+\r
+// === PROTOTYPES ===\r
+ int   Vesa_Install(char **Arguments);\r
+Uint64 Vesa_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);\r
+Uint64 Vesa_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);\r
+ int   Vesa_Ioctl(tVFS_Node *Node, int ID, void *Data);\r
+ int   Vesa_Int_SetMode(int Mode);\r
+ int   Vesa_Int_FindMode(tVideo_IOCtl_Mode *data);\r
+ int   Vesa_Int_ModeInfo(tVideo_IOCtl_Mode *data);\r
+\r
+// === GLOBALS ===\r
+MODULE_DEFINE(0, VERSION, Vesa, Vesa_Install, NULL, "PCI", "VM8086", NULL);\r
+tDevFS_Driver  gVesa_DriverStruct = {\r
+       NULL, "Vesa",\r
+       {\r
+       .Read = Vesa_Read,\r
+       .Write = Vesa_Write,\r
+       .IOCtl = Vesa_Ioctl\r
+       }\r
+};\r
+tSpinlock      glVesa_Lock;\r
+tVM8086        *gpVesa_BiosState;\r
+ int   giVesaCurrentMode = -1;\r
+ int   giVesaCurrentFormat = VIDEO_BUFFMT_TEXT;\r
+ int   giVesaDriverId = -1;\r
+char   *gVesaFramebuffer = (void*)0xC00A0000;\r
+tVesa_Mode     *gVesa_Modes;\r
+ int   giVesaModeCount = 0;\r
+ int   giVesaPageCount = 0;\r
+\r
+//CODE\r
+int Vesa_Install(char **Arguments)\r
+{\r
+       tVesa_CallInfo  *info;\r
+       tFarPtr infoPtr;\r
+       tVesa_CallModeInfo      *modeinfo;\r
+       tFarPtr modeinfoPtr;\r
+       Uint16  *modes;\r
+       int     i;\r
+       \r
+       // Allocate Info Block\r
+       gpVesa_BiosState = VM8086_Init();\r
+       info = VM8086_Allocate(gpVesa_BiosState, 512, &infoPtr.seg, &infoPtr.ofs);\r
+       modeinfo = VM8086_Allocate(gpVesa_BiosState, 512, &modeinfoPtr.seg, &modeinfoPtr.ofs);\r
+       // Set Requested Version\r
+       memcpy(info->signature, "VBE2", 4);\r
+       // Set Registers\r
+       gpVesa_BiosState->AX = 0x4F00;\r
+       gpVesa_BiosState->ES = infoPtr.seg;     gpVesa_BiosState->DI = infoPtr.ofs;\r
+       // Call Interrupt\r
+       VM8086_Int(gpVesa_BiosState, 0x10);\r
+       if(gpVesa_BiosState->AX != 0x004F) {\r
+               Log_Warning("Vesa", "Vesa_Install - VESA/VBE Unsupported (AX = 0x%x)\n", gpVesa_BiosState->AX);\r
+               return MODULE_ERR_NOTNEEDED;\r
+       }\r
+       \r
+       Log_Debug("Vesa", "info->VideoModes = %04x:%04x", info->VideoModes.seg, info->VideoModes.ofs);\r
+       modes = (Uint16 *) VM8086_GetPointer(gpVesa_BiosState, info->VideoModes.seg, info->VideoModes.ofs);\r
+       \r
+       // Read Modes\r
+       for( giVesaModeCount = 0; modes[giVesaModeCount] != 0xFFFF; giVesaModeCount++ );\r
+       gVesa_Modes = (tVesa_Mode *)malloc( giVesaModeCount * sizeof(tVesa_Mode) );\r
+       \r
+       // Insert Text Mode\r
+       gVesa_Modes[0].width = 80;\r
+       gVesa_Modes[0].height = 25;\r
+       gVesa_Modes[0].bpp = 12;\r
+       gVesa_Modes[0].code = 0x3;\r
+       gVesa_Modes[0].flags = 1;\r
+       gVesa_Modes[0].fbSize = 80*25*2;\r
+       gVesa_Modes[0].framebuffer = 0xB8000;\r
+       \r
+       for( i = 1; i < giVesaModeCount; i++ )\r
+       {\r
+               gVesa_Modes[i].code = modes[i];\r
+               // Get Mode info\r
+               gpVesa_BiosState->AX = 0x4F01;\r
+               gpVesa_BiosState->CX = gVesa_Modes[i].code;\r
+               gpVesa_BiosState->ES = modeinfoPtr.seg;\r
+               gpVesa_BiosState->DI = modeinfoPtr.ofs;\r
+               VM8086_Int(gpVesa_BiosState, 0x10);\r
+               \r
+               // Parse Info\r
+               gVesa_Modes[i].flags = 0;\r
+               if ( (modeinfo->attributes & 0x90) == 0x90 )\r
+               {\r
+                       gVesa_Modes[i].flags |= FLAG_LFB;\r
+                       gVesa_Modes[i].framebuffer = modeinfo->physbase;\r
+                       gVesa_Modes[i].fbSize = modeinfo->Xres*modeinfo->Yres*modeinfo->bpp/8;\r
+               } else {\r
+                       gVesa_Modes[i].framebuffer = 0;\r
+                       gVesa_Modes[i].fbSize = 0;\r
+               }\r
+               \r
+               gVesa_Modes[i].width = modeinfo->Xres;\r
+               gVesa_Modes[i].height = modeinfo->Yres;\r
+               gVesa_Modes[i].bpp = modeinfo->bpp;\r
+               \r
+               #if DEBUG\r
+               Log_Log("Vesa", "0x%x - %ix%ix%i",\r
+                       gVesa_Modes[i].code, gVesa_Modes[i].width, gVesa_Modes[i].height, gVesa_Modes[i].bpp);\r
+               #endif\r
+       }\r
+       \r
+       \r
+       // Install Device\r
+       giVesaDriverId = DevFS_AddDevice( &gVesa_DriverStruct );\r
+       if(giVesaDriverId == -1)        return MODULE_ERR_MISC;\r
+       \r
+       return MODULE_ERR_OK;\r
+}\r
+\r
+/* Read from the framebuffer\r
+ */\r
+Uint64 Vesa_Read(tVFS_Node *Node, Uint64 off, Uint64 len, void *buffer)\r
+{\r
+       #if DEBUG >= 2\r
+       LogF("Vesa_Read: () - NULL\n");\r
+       #endif\r
+       return 0;\r
+}\r
+\r
+/**\r
+ * \brief Write to the framebuffer\r
+ */\r
+Uint64 Vesa_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)\r
+{\r
+       ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);\r
+\r
+       if(Buffer == NULL) {\r
+               LEAVE('i', 0);\r
+               return 0;\r
+       }\r
+\r
+       // Default Text mode\r
+       if( giVesaCurrentMode == 0 )\r
+       {\r
+               Uint8   *fb = (Uint8 *)(KERNEL_BASE|0xB8000);\r
+               Uint32  *buf = Buffer;\r
+                int    rem;\r
+               \r
+               if( giVesaCurrentFormat != VIDEO_BUFFMT_TEXT ) {\r
+                       Log_Warning("VESA", "Vesa_Write - Mode 0 is not framebuffer");\r
+                       LEAVE('i', -1);\r
+                       return -1;\r
+               }\r
+               \r
+               if( Offset + Length > 25*80*8 ) {\r
+                       Log_Warning("VESA", "Vesa_Write - Framebuffer Overflow");\r
+                       LEAVE('i', 0);\r
+                       return 0;\r
+               }\r
+               \r
+               fb += 2*Offset;\r
+               for(rem = Length / sizeof(tVT_Char); rem --; fb += 2)\r
+               {\r
+                       if( *buf < 0x80 )\r
+                               *fb = *buf & 0x7F;\r
+                       else\r
+                               *fb = 0x00;\r
+                       buf ++;\r
+                       \r
+                       fb[1] = 0;\r
+                       fb[1] |= (*buf & 0x888) == 0x888 ? 0x8 : 0;\r
+                       fb[1] |= (*buf & 0x700) > 0x300 ? 0x4 : 0;\r
+                       fb[1] |= (*buf & 0x070) > 0x030 ? 0x2 : 0;\r
+                       fb[1] |= (*buf & 0x007) > 0x003 ? 0x1 : 0;\r
+                       fb[1] |= (*buf & 0x888000) == 0x888000 ? 0x80 : 0;\r
+                       fb[1] |= (*buf & 0x700000) > 0x300000 ? 0x40 : 0;\r
+                       fb[1] |= (*buf & 0x070000) > 0x030000 ? 0x20 : 0;\r
+                       fb[1] |= (*buf & 0x007000) > 0x003000 ? 0x10 : 0;\r
+                       buf ++;\r
+               }\r
+               Length /= sizeof(tVT_Char);\r
+               Length *= sizeof(tVT_Char);\r
+               LEAVE('X', Length);\r
+               return Length;\r
+       }\r
+\r
+       if( gVesa_Modes[giVesaCurrentMode].framebuffer == 0 ) {\r
+               Log_Warning("VESA", "Vesa_Write - Non-LFB Modes not yet supported.");\r
+               LEAVE('i', 0);\r
+               return 0;\r
+       }\r
+       \r
+       // Text Mode\r
+       switch( giVesaCurrentFormat )\r
+       {\r
+       case VIDEO_BUFFMT_TEXT:\r
+               {\r
+               tVT_Char        *chars = Buffer;\r
+                int    pitch = gVesa_Modes[giVesaCurrentMode].width * giVT_CharWidth;\r
+                int    x, y;\r
+               Uint32  *dest;\r
+                int    rem;\r
+               \r
+               Offset /= sizeof(tVT_Char);\r
+               dest = (void*)gVesaFramebuffer;\r
+               x = (Offset % gVesa_Modes[giVesaCurrentMode].width) * giVT_CharWidth;\r
+               y = (Offset / gVesa_Modes[giVesaCurrentMode].width) * giVT_CharHeight;\r
+               \r
+               // Sanity Check\r
+               if(y > gVesa_Modes[giVesaCurrentMode].height) {\r
+                       LEAVE('i', 0);\r
+                       return 0;\r
+               }\r
+               \r
+               dest += y * pitch;\r
+               dest += x * giVT_CharWidth;\r
+               for( rem = Length / sizeof(tVT_Char); rem--; )\r
+               {\r
+                       VT_Font_Render(\r
+                               chars->Ch,\r
+                               dest, pitch,\r
+                               VT_Colour12to24(chars->BGCol),\r
+                               VT_Colour12to24(chars->FGCol)\r
+                               );\r
+                       \r
+                       dest += giVT_CharWidth;\r
+                       \r
+                       chars ++;\r
+                       x += giVT_CharWidth;\r
+                       if( x >= pitch ) {\r
+                               x = 0;\r
+                               y += giVT_CharHeight;\r
+                               dest += pitch*(giVT_CharHeight-1);\r
+                       }\r
+               }\r
+               Length /= sizeof(tVT_Char);\r
+               Length *= sizeof(tVT_Char);\r
+               }\r
+               break;\r
+       \r
+       case VIDEO_BUFFMT_FRAMEBUFFER:\r
+               {\r
+               Uint8   *destBuf = (Uint8*) ((Uint)gVesaFramebuffer + (Uint)Offset);\r
+               \r
+               if(gVesa_Modes[giVesaCurrentMode].fbSize < Offset+Length)\r
+               {\r
+                       Log_Warning("VESA", "Vesa_Write - Framebuffer Overflow");\r
+                       LEAVE('i', 0);\r
+                       return 0;\r
+               }\r
+               \r
+               LOG("buffer = %p", Buffer);\r
+               LOG("Updating Framebuffer (%p to %p)", destBuf, destBuf + (Uint)Length);\r
+               \r
+               \r
+               // Copy to Frambuffer\r
+               memcpy(destBuf, Buffer, Length);\r
+               \r
+               LOG("BGA Framebuffer updated");\r
+               }\r
+               break;\r
+       default:\r
+               LEAVE('i', -1);\r
+               return -1;\r
+       }\r
+       \r
+       LEAVE('X', Length);\r
+       return Length;\r
+}\r
+\r
+/**\r
+ * \fn int Vesa_Ioctl(vfs_node *node, int id, void *data)\r
+ * \brief Handle messages to the device\r
+ */\r
+int Vesa_Ioctl(tVFS_Node *Node, int ID, void *Data)\r
+{\r
+        int    ret;\r
+       switch(ID)\r
+       {\r
+       case DRV_IOCTL_TYPE:    return DRV_TYPE_VIDEO;\r
+       case DRV_IOCTL_IDENT:   memcpy("VESA", Data, 4);        return 1;\r
+       case DRV_IOCTL_VERSION: return VERSION;\r
+       \r
+       case VIDEO_IOCTL_GETSETMODE:\r
+               if( !Data )     return giVesaCurrentMode;\r
+               return Vesa_Int_SetMode( *(int*)Data );\r
+       \r
+       case VIDEO_IOCTL_FINDMODE:\r
+               return Vesa_Int_FindMode((tVideo_IOCtl_Mode*)Data);\r
+       case VIDEO_IOCTL_MODEINFO:\r
+               return Vesa_Int_ModeInfo((tVideo_IOCtl_Mode*)Data);\r
+       \r
+       case VIDEO_IOCTL_SETBUFFORMAT:\r
+               ret = giVesaCurrentFormat;\r
+               if(Data)        giVesaCurrentFormat = *(int*)Data;\r
+               return ret;\r
+       \r
+       case VIDEO_IOCTL_REQLFB:        // Request Linear Framebuffer\r
+               return 0;\r
+       }\r
+       return 0;\r
+}\r
+\r
+int Vesa_Int_SetMode(int mode)\r
+{      \r
+       #if DEBUG\r
+       LogF("Vesa_Int_SetMode: (mode=%i)\n", mode);\r
+       #endif\r
+       \r
+       // Sanity Check values\r
+       if(mode < 0 || mode > giVesaModeCount)  return -1;\r
+       \r
+       // Check for fast return\r
+       if(mode == giVesaCurrentMode)   return 1;\r
+       \r
+       LOCK( &glVesa_Lock );\r
+       \r
+       gpVesa_BiosState->AX = 0x4F02;\r
+       gpVesa_BiosState->BX = gVesa_Modes[mode].code;\r
+       if(gVesa_Modes[mode].flags & FLAG_LFB) {\r
+               Log_Log("VESA", "Using LFB");\r
+               gpVesa_BiosState->BX |= 0x4000; // Bit 14 - Use LFB\r
+       }\r
+       \r
+       // Set Mode\r
+       VM8086_Int(gpVesa_BiosState, 0x10);\r
+       \r
+       // Map Framebuffer\r
+       MM_UnmapHWPages((tVAddr)gVesaFramebuffer, giVesaPageCount);\r
+       giVesaPageCount = (gVesa_Modes[mode].fbSize + 0xFFF) >> 12;\r
+       gVesaFramebuffer = (void*)MM_MapHWPages(gVesa_Modes[mode].framebuffer, giVesaPageCount);\r
+       \r
+       LogF("Vesa", "Framebuffer (Phys) = 0x%x", gVesa_Modes[mode].framebuffer);\r
+       LogF("Vesa", "Framebuffer (Virt) = 0x%x", gVesaFramebuffer);\r
+       \r
+       // Record Mode Set\r
+       giVesaCurrentMode = mode;\r
+       \r
+       RELEASE( &glVesa_Lock );\r
+       \r
+       return 1;\r
+}\r
+\r
+int Vesa_Int_FindMode(tVideo_IOCtl_Mode *data)\r
+{\r
+        int    i;\r
+        int    best = -1, bestFactor = 1000;\r
+        int    factor, tmp;\r
+       \r
+       ENTER("idata->width idata->height idata->bpp", data->width, data->height, data->bpp);\r
+       \r
+       for(i=0;i<giVesaModeCount;i++)\r
+       {\r
+               LOG("Mode %i (%ix%ix%i)", i, gVesa_Modes[i].width, gVesa_Modes[i].height, gVesa_Modes[i].bpp);\r
+       \r
+               if(gVesa_Modes[i].width == data->width\r
+               && gVesa_Modes[i].height == data->height\r
+               && gVesa_Modes[i].bpp == data->bpp)\r
+               {\r
+                       LOG("Perfect!");\r
+                       best = i;\r
+                       break;\r
+               }\r
+               \r
+               tmp = gVesa_Modes[i].width * gVesa_Modes[i].height * gVesa_Modes[i].bpp;\r
+               tmp -= data->width * data->height * data->bpp;\r
+               tmp = tmp < 0 ? -tmp : tmp;\r
+               factor = tmp * 100 / (data->width * data->height * data->bpp);\r
+               \r
+               LOG("factor = %i", factor);\r
+               \r
+               if(factor < bestFactor)\r
+               {\r
+                       bestFactor = factor;\r
+                       best = i;\r
+               }\r
+       }\r
+       data->id = best;\r
+       data->width = gVesa_Modes[best].width;\r
+       data->height = gVesa_Modes[best].height;\r
+       data->bpp = gVesa_Modes[best].bpp;\r
+       LEAVE('i', best);\r
+       return best;\r
+}\r
+\r
+int Vesa_Int_ModeInfo(tVideo_IOCtl_Mode *data)\r
+{\r
+       if(data->id < 0 || data->id > giVesaModeCount)  return -1;\r
+       data->width = gVesa_Modes[data->id].width;\r
+       data->height = gVesa_Modes[data->id].height;\r
+       data->bpp = gVesa_Modes[data->id].bpp;\r
+       return 1;\r
+}\r
diff --git a/Modules/Filesystems/Ext2/Makefile b/Modules/Filesystems/Ext2/Makefile
new file mode 100644 (file)
index 0000000..471ba49
--- /dev/null
@@ -0,0 +1,7 @@
+#
+#
+
+OBJ = ext2.o read.o dir.o write.o
+NAME = Ext2
+
+-include ../Makefile.tpl
diff --git a/Modules/Filesystems/Ext2/dir.c b/Modules/Filesystems/Ext2/dir.c
new file mode 100644 (file)
index 0000000..86092b0
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * Acess OS
+ * Ext2 Driver Version 1
+ */
+/**
+ * \file dir.c
+ * \brief Second Extended Filesystem Driver
+ * \todo Implement file full write support
+ */
+#define DEBUG  1
+#define VERBOSE        0
+#include "ext2_common.h"
+
+
+// === PROTOTYPES ===
+char           *Ext2_ReadDir(tVFS_Node *Node, int Pos);
+tVFS_Node      *Ext2_FindDir(tVFS_Node *Node, char *FileName);
+ int           Ext2_MkNod(tVFS_Node *Node, char *Name, Uint Flags);
+tVFS_Node      *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeId, char *Name);
+
+// === CODE ===
+/**
+ \fn char *Ext2_ReadDir(tVFS_Node *Node, int Pos)
+ \brief Reads a directory entry
+*/
+char *Ext2_ReadDir(tVFS_Node *Node, int Pos)
+{
+       tExt2_Inode     inode;
+       char    namebuf[EXT2_NAME_LEN+1];
+       tExt2_DirEnt    dirent;
+       Uint64  Base;   // Block's Base Address
+        int    block = 0, ofs = 0;
+        int    entNum = 0;
+       tExt2_Disk      *disk = Node->ImplPtr;
+       Uint    size;
+       
+       ENTER("pNode iPos", Node, Pos);
+       
+       // Read directory's inode
+       //Ext2_int_GetInode(Node, &inode);
+       Ext2_int_ReadInode(disk, Node->Inode, &inode);
+       size = inode.i_size;
+       
+       LOG("inode.i_block[0] = 0x%x", inode.i_block[0]);
+       
+       // Find Entry
+       // Get First Block
+       // - Do this ourselves as it is a simple operation
+       Base = inode.i_block[0] * disk->BlockSize;
+       while(Pos -- && size > 0)
+       {
+               VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent);
+               ofs += dirent.rec_len;
+               size -= dirent.rec_len;
+               entNum ++;
+               
+               if(ofs >= disk->BlockSize) {
+                       block ++;
+                       if( ofs > disk->BlockSize ) {
+                               Log_Warning("EXT2", "Directory Entry %i of inode %i extends over a block boundary, ignoring",
+                                       entNum-1, Node->Inode);
+                       }
+                       ofs = 0;
+                       Base = Ext2_int_GetBlockAddr( disk, inode.i_block, block );
+               }
+       }
+       
+       // Check for the end of the list
+       if(size <= 0) {
+               LEAVE('n');
+               return NULL;
+       }
+       
+       // Read Entry
+       VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent );
+       //LOG("dirent.inode = %i", dirent.inode);
+       //LOG("dirent.rec_len = %i", dirent.rec_len);
+       //LOG("dirent.name_len = %i", dirent.name_len);
+       VFS_ReadAt( disk->FD, Base+ofs+sizeof(tExt2_DirEnt), dirent.name_len, namebuf );
+       namebuf[ dirent.name_len ] = '\0';      // Cap off string
+       
+       
+       // Ignore . and .. (these are done in the VFS)
+       if( (namebuf[0] == '.' && namebuf[1] == '\0')
+       ||  (namebuf[0] == '.' && namebuf[1] == '.' && namebuf[2]=='\0')) {
+               LEAVE('p', VFS_SKIP);
+               return VFS_SKIP;        // Skip
+       }
+       
+       LEAVE('s', namebuf);
+       // Create new node
+       return strdup(namebuf);
+}
+
+/**
+ \fn tVFS_Node *Ext2_FindDir(tVFS_Node *node, char *filename)
+ \brief Gets information about a file
+ \param node   vfs node - Parent Node
+ \param filename       String - Name of file
+ \return VFS Node of file
+*/
+tVFS_Node *Ext2_FindDir(tVFS_Node *Node, char *Filename)
+{
+       tExt2_Disk      *disk = Node->ImplPtr;
+       tExt2_Inode     inode;
+       char    namebuf[EXT2_NAME_LEN+1];
+       tExt2_DirEnt    dirent;
+       Uint64  Base;   // Block's Base Address
+        int    block = 0, ofs = 0;
+        int    entNum = 0;
+       Uint    size;
+       
+       // Read directory's inode
+       Ext2_int_ReadInode(disk, Node->Inode, &inode);
+       size = inode.i_size;
+       
+       // Get First Block
+       // - Do this ourselves as it is a simple operation
+       Base = inode.i_block[0] * disk->BlockSize;
+       // Find File
+       while(size > 0)
+       {
+               VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent);
+               VFS_ReadAt( disk->FD, Base+ofs+sizeof(tExt2_DirEnt), dirent.name_len, namebuf );
+               namebuf[ dirent.name_len ] = '\0';      // Cap off string
+               // If it matches, create a node and return it
+               if(strcmp(namebuf, Filename) == 0)
+                       return Ext2_int_CreateNode( disk, dirent.inode, namebuf );
+               // Increment pointers
+               ofs += dirent.rec_len;
+               size -= dirent.rec_len;
+               entNum ++;
+               
+               // Check for end of block
+               if(ofs >= disk->BlockSize) {
+                       block ++;
+                       if( ofs > disk->BlockSize ) {
+                               Log_Warning("EXT2", "Directory Entry %i of inode %i extends over a block boundary, ignoring",
+                                       entNum-1, Node->Inode);
+                       }
+                       ofs = 0;
+                       Base = Ext2_int_GetBlockAddr( disk, inode.i_block, block );
+               }
+       }
+       
+       return NULL;
+}
+
+/**
+ * \fn int Ext2_MkNod(tVFS_Node *Parent, char *Name, Uint Flags)
+ * \brief Create a new node
+ */
+int Ext2_MkNod(tVFS_Node *Parent, char *Name, Uint Flags)
+{
+       return 0;
+}
+
+// ---- INTERNAL FUNCTIONS ----
+/**
+ * \fn vfs_node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeID, char *Name)
+ * \brief Create a new VFS Node
+ */
+tVFS_Node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeID, char *Name)
+{
+       tExt2_Inode     inode;
+       tVFS_Node       retNode;
+       tVFS_Node       *tmpNode;
+       
+       if( !Ext2_int_ReadInode(Disk, InodeID, &inode) )
+               return NULL;
+       
+       if( (tmpNode = Inode_GetCache(Disk->CacheID, InodeID)) )
+               return tmpNode;
+       
+       
+       // Set identifiers
+       retNode.Inode = InodeID;
+       retNode.ImplPtr = Disk;
+       
+       // Set file length
+       retNode.Size = inode.i_size;
+       
+       // Set Access Permissions
+       retNode.UID = inode.i_uid;
+       retNode.GID = inode.i_gid;
+       retNode.NumACLs = 3;
+       retNode.ACLs = VFS_UnixToAcessACL(inode.i_mode & 0777, inode.i_uid, inode.i_gid);
+       
+       //  Set Function Pointers
+       retNode.Read = Ext2_Read;
+       retNode.Write = Ext2_Write;
+       retNode.Close = Ext2_CloseFile;
+       
+       switch(inode.i_mode & EXT2_S_IFMT)
+       {
+       // Symbolic Link
+       case EXT2_S_IFLNK:
+               retNode.Flags = VFS_FFLAG_SYMLINK;
+               break;
+       // Regular File
+       case EXT2_S_IFREG:
+               retNode.Flags = 0;
+               retNode.Size |= (Uint64)inode.i_dir_acl << 32;
+               break;
+       // Directory
+       case EXT2_S_IFDIR:
+               retNode.ReadDir = Ext2_ReadDir;
+               retNode.FindDir = Ext2_FindDir;
+               retNode.MkNod = Ext2_MkNod;
+               //retNode.Relink = Ext2_Relink;
+               retNode.Flags = VFS_FFLAG_DIRECTORY;
+               break;
+       // Unknown, Write protect and hide it to be safe 
+       default:
+               retNode.Flags = VFS_FFLAG_READONLY;//|VFS_FFLAG_HIDDEN;
+               break;
+       }
+       
+       // Check if the file should be hidden
+       //if(Name[0] == '.')    retNode.Flags |= VFS_FFLAG_HIDDEN;
+       
+       // Set Timestamps
+       retNode.ATime = inode.i_atime * 1000;
+       retNode.MTime = inode.i_mtime * 1000;
+       retNode.CTime = inode.i_ctime * 1000;
+       
+       // Save in node cache and return saved node
+       return Inode_CacheNode(Disk->CacheID, &retNode);
+}
diff --git a/Modules/Filesystems/Ext2/ext2.c b/Modules/Filesystems/Ext2/ext2.c
new file mode 100644 (file)
index 0000000..ac3d7e5
--- /dev/null
@@ -0,0 +1,334 @@
+/*\r
+ * Acess OS\r
+ * Ext2 Driver Version 1\r
+ */\r
+/**\r
+ * \file fs/ext2.c\r
+ * \brief Second Extended Filesystem Driver\r
+ * \todo Implement file full write support\r
+ */\r
+#define DEBUG  1\r
+#define VERBOSE        0\r
+#include "ext2_common.h"\r
+#include <modules.h>\r
+\r
+// === PROTOTYPES ===\r
+ int   Ext2_Install(char **Arguments);\r
+// Interface Functions\r
+tVFS_Node      *Ext2_InitDevice(char *Device, char **Options);\r
+void           Ext2_Unmount(tVFS_Node *Node);\r
+void           Ext2_CloseFile(tVFS_Node *Node);\r
+// Internal Helpers\r
+ int           Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode);\r
+Uint64         Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum);\r
+Uint32         Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent);\r
+void           Ext2_int_UpdateSuperblock(tExt2_Disk *Disk);\r
+\r
+// === SEMI-GLOBALS ===\r
+MODULE_DEFINE(0, 0x5B /*v0.90*/, FS_Ext2, Ext2_Install, NULL);\r
+tExt2_Disk     gExt2_disks[6];\r
+ int   giExt2_count = 0;\r
+tVFS_Driver    gExt2_FSInfo = {\r
+       "ext2", 0, Ext2_InitDevice, Ext2_Unmount, NULL\r
+       };\r
+\r
+// === CODE ===\r
+/**\r
+ * \fn int Ext2_Install(char **Arguments)\r
+ * \brief Install the Ext2 Filesystem Driver\r
+ */\r
+int Ext2_Install(char **Arguments)\r
+{\r
+       VFS_AddDriver( &gExt2_FSInfo );\r
+       return MODULE_ERR_OK;\r
+}\r
+\r
+/**\r
+ \fn tVFS_Node *Ext2_InitDevice(char *Device, char **Options)\r
+ \brief Initializes a device to be read by by the driver\r
+ \param Device String - Device to read from\r
+ \param Options        NULL Terminated array of option strings\r
+ \return Root Node\r
+*/\r
+tVFS_Node *Ext2_InitDevice(char *Device, char **Options)\r
+{\r
+       tExt2_Disk      *disk;\r
+        int    fd;\r
+        int    groupCount;\r
+       tExt2_SuperBlock        sb;\r
+       tExt2_Inode     inode;\r
+       \r
+       ENTER("sDevice pOptions", Device, Options);\r
+       \r
+       // Open Disk\r
+       fd = VFS_Open(Device, VFS_OPENFLAG_READ|VFS_OPENFLAG_WRITE);            //Open Device\r
+       if(fd == -1) {\r
+               Log_Warning("EXT2", "Unable to open '%s'", Device);\r
+               LEAVE('n');\r
+               return NULL;\r
+       }\r
+       \r
+       // Read Superblock at offset 1024\r
+       VFS_ReadAt(fd, 1024, 1024, &sb);        // Read Superblock\r
+       \r
+       // Sanity Check Magic value\r
+       if(sb.s_magic != 0xEF53) {\r
+               Log_Warning("EXT2", "Volume '%s' is not an EXT2 volume", Device);\r
+               VFS_Close(fd);\r
+               LEAVE('n');\r
+               return NULL;\r
+       }\r
+       \r
+       // Get Group count\r
+       groupCount = DivUp(sb.s_blocks_count, sb.s_blocks_per_group);\r
+       LOG("groupCount = %i", groupCount);\r
+       \r
+       // Allocate Disk Information\r
+       disk = malloc(sizeof(tExt2_Disk) + sizeof(tExt2_Group)*groupCount);\r
+       if(!disk) {\r
+               Log_Warning("EXT2", "Unable to allocate disk structure");\r
+               VFS_Close(fd);\r
+               LEAVE('n');\r
+               return NULL;\r
+       }\r
+       disk->FD = fd;\r
+       memcpy(&disk->SuperBlock, &sb, 1024);\r
+       disk->GroupCount = groupCount;\r
+       \r
+       // Get an inode cache handle\r
+       disk->CacheID = Inode_GetHandle();\r
+       \r
+       // Get Block Size\r
+       LOG("s_log_block_size = 0x%x", sb.s_log_block_size);\r
+       disk->BlockSize = 1024 << sb.s_log_block_size;\r
+       \r
+       // Read Group Information\r
+       VFS_ReadAt(\r
+               disk->FD,\r
+               sb.s_first_data_block * disk->BlockSize + 1024,\r
+               sizeof(tExt2_Group)*groupCount,\r
+               disk->Groups\r
+               );\r
+       \r
+       #if VERBOSE\r
+       LOG("Block Group 0");\r
+       LOG(".bg_block_bitmap = 0x%x", disk->Groups[0].bg_block_bitmap);\r
+       LOG(".bg_inode_bitmap = 0x%x", disk->Groups[0].bg_inode_bitmap);\r
+       LOG(".bg_inode_table = 0x%x", disk->Groups[0].bg_inode_table);\r
+       LOG("Block Group 1");\r
+       LOG(".bg_block_bitmap = 0x%x", disk->Groups[1].bg_block_bitmap);\r
+       LOG(".bg_inode_bitmap = 0x%x", disk->Groups[1].bg_inode_bitmap);\r
+       LOG(".bg_inode_table = 0x%x", disk->Groups[1].bg_inode_table);\r
+       #endif\r
+       \r
+       // Get root Inode\r
+       Ext2_int_ReadInode(disk, 2, &inode);\r
+       \r
+       // Create Root Node\r
+       memset(&disk->RootNode, 0, sizeof(tVFS_Node));\r
+       disk->RootNode.Inode = 2;       // Root inode ID\r
+       disk->RootNode.ImplPtr = disk;  // Save disk pointer\r
+       disk->RootNode.Size = -1;       // Fill in later (on readdir)\r
+       disk->RootNode.Flags = VFS_FFLAG_DIRECTORY;\r
+       \r
+       disk->RootNode.ReadDir = Ext2_ReadDir;\r
+       disk->RootNode.FindDir = Ext2_FindDir;\r
+       //disk->RootNode.Relink = Ext2_Relink;\r
+       \r
+       // Complete root node\r
+       disk->RootNode.UID = inode.i_uid;\r
+       disk->RootNode.GID = inode.i_gid;\r
+       disk->RootNode.NumACLs = 1;\r
+       disk->RootNode.ACLs = &gVFS_ACL_EveryoneRW;\r
+       \r
+       #if DEBUG\r
+       LOG("inode.i_size = 0x%x", inode.i_size);\r
+       LOG("inode.i_block[0] = 0x%x", inode.i_block[0]);\r
+       #endif\r
+       \r
+       LEAVE('p', &disk->RootNode);\r
+       return &disk->RootNode;\r
+}\r
+\r
+/**\r
+ * \fn void Ext2_Unmount(tVFS_Node *Node)\r
+ * \brief Close a mounted device\r
+ */\r
+void Ext2_Unmount(tVFS_Node *Node)\r
+{\r
+       tExt2_Disk      *disk = Node->ImplPtr;\r
+       \r
+       VFS_Close( disk->FD );\r
+       Inode_ClearCache( disk->CacheID );\r
+       memset(disk, 0, sizeof(tExt2_Disk)+disk->GroupCount*sizeof(tExt2_Group));\r
+       free(disk);\r
+}\r
+\r
+/**\r
+ * \fn void Ext2_CloseFile(tVFS_Node *Node)\r
+ * \brief Close a file (Remove it from the cache)\r
+ */\r
+void Ext2_CloseFile(tVFS_Node *Node)\r
+{\r
+       tExt2_Disk      *disk = Node->ImplPtr;\r
+       Inode_UncacheNode(disk->CacheID, Node->Inode);\r
+       return ;\r
+}\r
+\r
+//==================================\r
+//=       INTERNAL FUNCTIONS       =\r
+//==================================\r
+/**\r
+ * \fn int Ext2_int_ReadInode(tExt2_Disk *Disk, Uint InodeId, tExt2_Inode *Inode)\r
+ * \brief Read an inode into memory\r
+ */\r
+int Ext2_int_ReadInode(tExt2_Disk *Disk, Uint32 InodeId, tExt2_Inode *Inode)\r
+{\r
+        int    group, subId;\r
+       \r
+       ENTER("pDisk iInodeId pInode", Disk, InodeId, Inode);\r
+       \r
+       if(InodeId == 0)        return 0;\r
+       \r
+       InodeId --;     // Inodes are numbered starting at 1\r
+       \r
+       group = InodeId / Disk->SuperBlock.s_inodes_per_group;\r
+       subId = InodeId % Disk->SuperBlock.s_inodes_per_group;\r
+       \r
+       LOG("group=%i, subId = %i", group, subId);\r
+       \r
+       // Read Inode\r
+       VFS_ReadAt(Disk->FD,\r
+               Disk->Groups[group].bg_inode_table * Disk->BlockSize + sizeof(tExt2_Inode)*subId,\r
+               sizeof(tExt2_Inode),\r
+               Inode);\r
+       \r
+       LEAVE('i', 1);\r
+       return 1;\r
+}\r
+\r
+/**\r
+ * \brief Write a modified inode out to disk\r
+ */\r
+int Ext2_int_WriteInode(tExt2_Disk *Disk, Uint32 InodeId, tExt2_Inode *Inode)\r
+{\r
+        int    group, subId;\r
+       ENTER("pDisk iInodeId pInode", Disk, InodeId, Inode);\r
+       \r
+       if(InodeId == 0) {\r
+               LEAVE('i', 0);\r
+               return 0;\r
+       }\r
+       \r
+       InodeId --;     // Inodes are numbered starting at 1\r
+       \r
+       group = InodeId / Disk->SuperBlock.s_inodes_per_group;\r
+       subId = InodeId % Disk->SuperBlock.s_inodes_per_group;\r
+       \r
+       LOG("group=%i, subId = %i", group, subId);\r
+       \r
+       // Write Inode\r
+       VFS_WriteAt(Disk->FD,\r
+               Disk->Groups[group].bg_inode_table * Disk->BlockSize + sizeof(tExt2_Inode)*subId,\r
+               sizeof(tExt2_Inode),\r
+               Inode\r
+               );\r
+       \r
+       LEAVE('i', 1);\r
+       return 1;\r
+}\r
+\r
+/**\r
+ * \fn Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum)\r
+ * \brief Get the address of a block from an inode's list\r
+ * \param Disk Disk information structure\r
+ * \param Blocks       Pointer to an inode's block list\r
+ * \param BlockNum     Block index in list\r
+ */\r
+Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum)\r
+{\r
+       Uint32  *iBlocks;\r
+        int    dwPerBlock = Disk->BlockSize / 4;\r
+       \r
+       // Direct Blocks\r
+       if(BlockNum < 12)\r
+               return (Uint64)Blocks[BlockNum] * Disk->BlockSize;\r
+       \r
+       // Single Indirect Blocks\r
+       iBlocks = malloc( Disk->BlockSize );\r
+       VFS_ReadAt(Disk->FD, (Uint64)Blocks[12]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
+       \r
+       BlockNum -= 12;\r
+       if(BlockNum < dwPerBlock)\r
+       {\r
+               BlockNum = iBlocks[BlockNum];\r
+               free(iBlocks);\r
+               return (Uint64)BlockNum * Disk->BlockSize;\r
+       }\r
+       \r
+       BlockNum -= dwPerBlock;\r
+       // Double Indirect Blocks\r
+       if(BlockNum < dwPerBlock*dwPerBlock)\r
+       {\r
+               VFS_ReadAt(Disk->FD, (Uint64)Blocks[13]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
+               VFS_ReadAt(Disk->FD, (Uint64)iBlocks[BlockNum/dwPerBlock]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
+               BlockNum = iBlocks[BlockNum%dwPerBlock];\r
+               free(iBlocks);\r
+               return (Uint64)BlockNum * Disk->BlockSize;\r
+       }\r
+       \r
+       BlockNum -= dwPerBlock*dwPerBlock;\r
+       // Triple Indirect Blocks\r
+       VFS_ReadAt(Disk->FD, (Uint64)Blocks[14]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
+       VFS_ReadAt(Disk->FD, (Uint64)iBlocks[BlockNum/(dwPerBlock*dwPerBlock)]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
+       VFS_ReadAt(Disk->FD, (Uint64)iBlocks[(BlockNum/dwPerBlock)%dwPerBlock]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
+       BlockNum = iBlocks[BlockNum%dwPerBlock];\r
+       free(iBlocks);\r
+       return (Uint64)BlockNum * Disk->BlockSize;\r
+}\r
+\r
+/**\r
+ * \fn Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent)\r
+ * \brief Allocate an inode (from the current group preferably)\r
+ * \param Disk EXT2 Disk Information Structure\r
+ * \param Parent       Inode ID of the parent (used to locate the child nearby)\r
+ */\r
+Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent)\r
+{\r
+//     Uint    block = (Parent - 1) / Disk->SuperBlock.s_inodes_per_group;\r
+       Log_Warning("EXT2", "Ext2_int_AllocateInode is unimplemented");\r
+       return 0;\r
+}\r
+\r
+/**\r
+ * \fn void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk)\r
+ * \brief Updates the superblock\r
+ */\r
+void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk)\r
+{\r
+        int    bpg = Disk->SuperBlock.s_blocks_per_group;\r
+        int    ngrp = Disk->SuperBlock.s_blocks_count / bpg;\r
+        int    i;\r
+        \r
+       // Update Primary\r
+       VFS_WriteAt(Disk->FD, 1024, 1024, &Disk->SuperBlock);\r
+       \r
+       // Secondaries\r
+       // at Block Group 1, 3^n, 5^n, 7^n\r
+       \r
+       // 1\r
+       if(ngrp <= 1)   return;\r
+       VFS_WriteAt(Disk->FD, 1*bpg*Disk->BlockSize, 1024, &Disk->SuperBlock);\r
+       \r
+       // Powers of 3\r
+       for( i = 3; i < ngrp; i *= 3 )\r
+               VFS_WriteAt(Disk->FD, i*bpg*Disk->BlockSize, 1024, &Disk->SuperBlock);\r
+       \r
+       // Powers of 5\r
+       for( i = 5; i < ngrp; i *= 5 )\r
+               VFS_WriteAt(Disk->FD, i*bpg*Disk->BlockSize, 1024, &Disk->SuperBlock);\r
+       \r
+       // Powers of 7\r
+       for( i = 7; i < ngrp; i *= 7 )\r
+               VFS_WriteAt(Disk->FD, i*bpg*Disk->BlockSize, 1024, &Disk->SuperBlock);\r
+}\r
diff --git a/Modules/Filesystems/Ext2/ext2_common.h b/Modules/Filesystems/Ext2/ext2_common.h
new file mode 100644 (file)
index 0000000..877b71d
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Acess OS
+ * Ext2 Driver Version 1
+ */
+/**
+ * \file ext2_common.h
+ * \brief Second Extended Filesystem Driver
+ */
+#ifndef _EXT2_COMMON_H
+#define _EXT2_COMMON_H
+#include <acess.h>
+#include <vfs.h>
+#include "ext2fs.h"
+
+#define EXT2_UPDATE_WRITEBACK  1
+
+// === STRUCTURES ===
+typedef struct {
+        int    FD;
+        int    CacheID;
+       tVFS_Node       RootNode;
+       
+       tExt2_SuperBlock        SuperBlock;
+        int    BlockSize;
+        
+        int    GroupCount;
+       tExt2_Group             Groups[];
+} tExt2_Disk;
+
+// === FUNCTIONS ===
+// --- Common ---
+extern void    Ext2_CloseFile(tVFS_Node *Node);
+extern Uint64  Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum);
+extern void    Ext2_int_UpdateSuperblock(tExt2_Disk *Disk);
+extern int     Ext2_int_ReadInode(tExt2_Disk *Disk, Uint32 InodeId, tExt2_Inode *Inode);
+extern int     Ext2_int_WriteInode(tExt2_Disk *Disk, Uint32 InodeId, tExt2_Inode *Inode);
+// --- Dir ---
+extern char    *Ext2_ReadDir(tVFS_Node *Node, int Pos);
+extern tVFS_Node       *Ext2_FindDir(tVFS_Node *Node, char *FileName);
+extern int     Ext2_MkNod(tVFS_Node *Node, char *Name, Uint Flags);
+// --- Read ---
+extern Uint64  Ext2_Read(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer);
+// --- Write ---
+extern Uint64  Ext2_Write(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer);
+
+#endif
diff --git a/Modules/Filesystems/Ext2/ext2fs.h b/Modules/Filesystems/Ext2/ext2fs.h
new file mode 100644 (file)
index 0000000..8fd87ce
--- /dev/null
@@ -0,0 +1,156 @@
+/**\r
+ * Acess2\r
+ * \file ext2fs.h\r
+ * \brief EXT2 Filesystem Driver\r
+ */\r
+#ifndef _EXT2FS_H_\r
+#define _EXT2FS_H_\r
+\r
+/**\r
+ \name Inode Flag Values\r
+ \{\r
+*/\r
+#define EXT2_S_IFMT            0xF000  //!< Format Mask\r
+#define EXT2_S_IFSOCK  0xC000  //!< Socket\r
+#define EXT2_S_IFLNK   0xA000  //!< Symbolic Link\r
+#define EXT2_S_IFREG   0x8000  //!< Regular File\r
+#define EXT2_S_IFBLK   0x6000  //!< Block Device\r
+#define EXT2_S_IFDIR   0x4000  //!< Directory\r
+#define EXT2_S_IFCHR   0x2000  //!< Character Device\r
+#define EXT2_S_IFIFO   0x1000  //!< FIFO\r
+#define EXT2_S_ISUID   0x0800  //!< SUID\r
+#define EXT2_S_ISGID   0x0400  //!< SGID\r
+#define EXT2_S_ISVTX   0x0200  //!< sticky bit\r
+#define EXT2_S_IRWXU   0700    //!< user access rights mask\r
+#define EXT2_S_IRUSR   0400    //!< Owner Read\r
+#define EXT2_S_IWUSR   0200    //!< Owner Write\r
+#define EXT2_S_IXUSR   0100    //!< Owner Execute\r
+#define EXT2_S_IRWXG   0070    //!< Group Access rights mask\r
+#define EXT2_S_IRGRP   0040    //!< Group Read\r
+#define EXT2_S_IWGRP   0020    //!< Group Write\r
+#define EXT2_S_IXGRP   0010    //!< Group Execute\r
+#define EXT2_S_IRWXO   0007    //!< Global Access rights mask\r
+#define EXT2_S_IROTH   0004    //!< Global Read\r
+#define EXT2_S_IWOTH   0002    //!< Global Write\r
+#define EXT2_S_IXOTH   0001    //!< Global Execute\r
+//! \}\r
+\r
+#define EXT2_NAME_LEN 255      //!< Maximum Name Length\r
+\r
+// === TYPEDEFS ===\r
+typedef struct ext2_inode_s                    tExt2_Inode;    //!< Inode Type\r
+typedef struct ext2_super_block_s      tExt2_SuperBlock;       //!< Superblock Type\r
+typedef struct ext2_group_desc_s       tExt2_Group;    //!< Group Descriptor Type\r
+typedef struct ext2_dir_entry_s                tExt2_DirEnt;   //!< Directory Entry Type\r
+\r
+// === STRUCTURES ===\r
+/**\r
+ * \brief EXT2 Superblock Structure\r
+ */\r
+struct ext2_super_block_s {\r
+       Uint32  s_inodes_count;         //!< Inodes count\r
+       Uint32  s_blocks_count;         //!< Blocks count\r
+       Uint32  s_r_blocks_count;       //!< Reserved blocks count\r
+       Uint32  s_free_blocks_count;    //!< Free blocks count\r
+       Uint32  s_free_inodes_count;    //!< Free inodes count\r
+       Uint32  s_first_data_block;     //!< First Data Block\r
+       Uint32  s_log_block_size;       //!< Block size\r
+       Sint32  s_log_frag_size;        //!< Fragment size\r
+       Uint32  s_blocks_per_group;     //!< Number Blocks per group\r
+       Uint32  s_frags_per_group;      //!< Number Fragments per group\r
+       Uint32  s_inodes_per_group;     //!< Number Inodes per group\r
+       Uint32  s_mtime;                        //!< Mount time\r
+       Uint32  s_wtime;                        //!< Write time\r
+       Uint16  s_mnt_count;            //!< Mount count\r
+       Sint16  s_max_mnt_count;        //!< Maximal mount count\r
+       Uint16  s_magic;                        //!< Magic signature\r
+       Uint16  s_state;                        //!< File system state\r
+       Uint16  s_errors;                       //!< Behaviour when detecting errors\r
+       Uint16  s_pad;                          //!< Padding\r
+       Uint32  s_lastcheck;            //!< time of last check\r
+       Uint32  s_checkinterval;        //!< max. time between checks\r
+       Uint32  s_creator_os;           //!< Formatting OS\r
+       Uint32  s_rev_level;            //!< Revision level\r
+       Uint16  s_def_resuid;           //!< Default uid for reserved blocks\r
+       Uint16  s_def_resgid;           //!< Default gid for reserved blocks\r
+       Uint32  s_reserved[235];        //!< Padding to the end of the block\r
+};\r
+\r
+/**\r
+ * \struct ext2_inode_s\r
+ * \brief EXT2 Inode Definition\r
+ */\r
+struct ext2_inode_s {\r
+       Uint16 i_mode;  //!< File mode\r
+       Uint16 i_uid;   //!< Owner Uid\r
+       Uint32 i_size;  //!< Size in bytes\r
+       Uint32 i_atime; //!< Access time\r
+       Uint32 i_ctime; //!< Creation time\r
+       Uint32 i_mtime; //!< Modification time\r
+       Uint32 i_dtime; //!< Deletion Time\r
+       Uint16 i_gid;   //!< Group Id\r
+       Uint16 i_links_count;   //!< Links count\r
+       Uint32 i_blocks;        //!< Number of blocks allocated for the file\r
+       Uint32 i_flags; //!< File flags\r
+       union {\r
+               Uint32 linux_reserved1; //!< Linux: Reserved\r
+               Uint32 hurd_translator; //!< HURD: Translator\r
+               Uint32 masix_reserved1; //!< Masix: Reserved\r
+       } osd1; //!< OS dependent 1\r
+       Uint32 i_block[15];     //!< Pointers to blocks\r
+       Uint32 i_version;       //!< File version (for NFS)\r
+       Uint32 i_file_acl;      //!< File ACL\r
+       Uint32 i_dir_acl;       //!< Directory ACL / Extended File Size\r
+       Uint32 i_faddr;         //!< Fragment address\r
+       union {\r
+               struct {\r
+                       Uint8 l_i_frag; //!< Fragment number\r
+                       Uint8 l_i_fsize;        //!< Fragment size\r
+                       Uint16 i_pad1;  //!< Padding\r
+                       Uint32 l_i_reserved2[2];        //!< Reserved\r
+               } linux2;\r
+               struct {\r
+                       Uint8 h_i_frag; //!< Fragment number\r
+                       Uint8 h_i_fsize; //!< Fragment size\r
+                       Uint16 h_i_mode_high;   //!< Mode High Bits\r
+                       Uint16 h_i_uid_high;    //!< UID High Bits\r
+                       Uint16 h_i_gid_high;    //!< GID High Bits\r
+                       Uint32 h_i_author;      //!< Creator ID\r
+               } hurd2;\r
+               struct {\r
+                       Uint8 m_i_frag; //!< Fragment number\r
+                       Uint8 m_i_fsize;        //!< Fragment size\r
+                       Uint16 m_pad1;  //!< Padding\r
+                       Uint32 m_i_reserved2[2];        //!< reserved\r
+               } masix2;\r
+       } osd2; //!< OS dependent 2\r
+};\r
+\r
+/**\r
+ * \struct ext2_group_desc_s\r
+ * \brief EXT2 Group Descriptor\r
+ */\r
+struct ext2_group_desc_s {\r
+       Uint32  bg_block_bitmap;        //!< Blocks bitmap block\r
+       Uint32  bg_inode_bitmap;        //!< Inodes bitmap block\r
+       Uint32  bg_inode_table; //!< Inodes table block\r
+       Uint16  bg_free_blocks_count;   //!< Free blocks count\r
+       Uint16  bg_free_inodes_count;   //!< Free inodes count\r
+       Uint16  bg_used_dirs_count;     //!< Directories count\r
+       Uint16  bg_pad; //!< Padding\r
+       Uint32  bg_reserved[3]; //!< Reserved\r
+};\r
+\r
+/**\r
+ * \brief EXT2 Directory Entry\r
+ * \note The name may take up less than 255 characters\r
+ */\r
+struct ext2_dir_entry_s {\r
+       Uint32  inode;          //!< Inode number\r
+       Uint16  rec_len;        //!< Directory entry length\r
+       Uint8   name_len;       //!< Short Name Length\r
+       Uint8   type;           //!< File Type\r
+       char    name[];         //!< File name\r
+};\r
+\r
+#endif\r
diff --git a/Modules/Filesystems/Ext2/read.c b/Modules/Filesystems/Ext2/read.c
new file mode 100644 (file)
index 0000000..81f5ee6
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Acess OS
+ * Ext2 Driver Version 1
+ */
+/**
+ * \file read.c
+ * \brief Second Extended Filesystem Driver
+ * \todo Implement file full write support
+ */
+#define DEBUG  1
+#define VERBOSE        0
+#include "ext2_common.h"
+
+// === PROTOTYPES ===
+Uint64         Ext2_Read(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer);
+
+// === CODE ===
+/**
+ * \fn Uint64 Ext2_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
+ * \brief Read from a file
+ */
+Uint64 Ext2_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
+{
+       tExt2_Disk      *disk = Node->ImplPtr;
+       tExt2_Inode     inode;
+       Uint64  base;
+       Uint    block;
+       Uint64  remLen;
+       
+       ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);
+       
+       // Get Inode
+       Ext2_int_ReadInode(disk, Node->Inode, &inode);
+       
+       // Sanity Checks
+       if(Offset >= inode.i_size) {
+               LEAVE('i', 0);
+               return 0;
+       }
+       if(Offset + Length > inode.i_size)
+               Length = inode.i_size - Offset;
+       
+       block = Offset / disk->BlockSize;
+       Offset = Offset / disk->BlockSize;
+       base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
+       if(base == 0) {
+               Warning("[EXT2 ] NULL Block Detected in INode 0x%llx", Node->Inode);
+               LEAVE('i', 0);
+               return 0;
+       }
+       
+       // Read only block
+       if(Length <= disk->BlockSize - Offset)
+       {
+               VFS_ReadAt( disk->FD, base+Offset, Length, Buffer);
+               LEAVE('X', Length);
+               return Length;
+       }
+       
+       // Read first block
+       remLen = Length;
+       VFS_ReadAt( disk->FD, base + Offset, disk->BlockSize - Offset, Buffer);
+       remLen -= disk->BlockSize - Offset;
+       Buffer += disk->BlockSize - Offset;
+       block ++;
+       
+       // Read middle blocks
+       while(remLen > disk->BlockSize)
+       {
+               base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
+               if(base == 0) {
+                       Warning("[EXT2 ] NULL Block Detected in INode 0x%llx", Node->Inode);
+                       LEAVE('i', 0);
+                       return 0;
+               }
+               VFS_ReadAt( disk->FD, base, disk->BlockSize, Buffer);
+               Buffer += disk->BlockSize;
+               remLen -= disk->BlockSize;
+               block ++;
+       }
+       
+       // Read last block
+       base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
+       VFS_ReadAt( disk->FD, base, remLen, Buffer);
+       
+       LEAVE('X', Length);
+       return Length;
+}
diff --git a/Modules/Filesystems/Ext2/write.c b/Modules/Filesystems/Ext2/write.c
new file mode 100644 (file)
index 0000000..e52ebf7
--- /dev/null
@@ -0,0 +1,369 @@
+/*
+ * Acess OS
+ * Ext2 Driver Version 1
+ */
+/**
+ * \file write.c
+ * \brief Second Extended Filesystem Driver
+ * \todo Implement file full write support
+ */
+#define DEBUG  1
+#define VERBOSE        0
+#include "ext2_common.h"
+
+// === PROTOYPES ===
+Uint64         Ext2_Write(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer);
+Uint32         Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock);
+void   Ext2_int_DeallocateBlock(tExt2_Disk *Disk, Uint32 Block);
+ int   Ext2_int_AppendBlock(tExt2_Disk *Disk, tExt2_Inode *Inode, Uint32 Block);
+
+// === CODE ===
+/**
+ * \fn Uint64 Ext2_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
+ * \brief Write to a file
+ */
+Uint64 Ext2_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
+{
+       tExt2_Disk      *disk = Node->ImplPtr;
+       tExt2_Inode     inode;
+       Uint64  base;
+       Uint64  retLen;
+       Uint    block;
+       Uint64  allocSize;
+        int    bNewBlocks = 0;
+       
+       Debug_HexDump("Ext2_Write", Buffer, Length);
+       
+       Ext2_int_ReadInode(disk, Node->Inode, &inode);
+       
+       // Get the ammount of space already allocated
+       // - Round size up to block size
+       // - block size is a power of two, so this will work
+       allocSize = (inode.i_size + disk->BlockSize-1) & ~(disk->BlockSize-1);
+       
+       // Are we writing to inside the allocated space?
+       if( Offset > allocSize )        return 0;
+       
+       if( Offset < allocSize )
+       {
+               // Will we go out of it?
+               if(Offset + Length > allocSize) {
+                       bNewBlocks = 1;
+                       retLen = allocSize - Offset;
+               } else
+                       retLen = Length;
+               
+               // Within the allocated space
+               block = Offset / disk->BlockSize;
+               Offset %= disk->BlockSize;
+               base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
+               
+               // Write only block (if only one)
+               if(Offset + retLen <= disk->BlockSize) {
+                       VFS_WriteAt(disk->FD, base+Offset, retLen, Buffer);
+                       if(!bNewBlocks) return Length;
+                       goto addBlocks; // Ugh! A goto, but it seems unavoidable
+               }
+               
+               // Write First Block
+               VFS_WriteAt(disk->FD, base+Offset, disk->BlockSize-Offset, Buffer);
+               Buffer += disk->BlockSize-Offset;
+               retLen -= disk->BlockSize-Offset;
+               block ++;
+               
+               // Write middle blocks
+               while(retLen > disk->BlockSize)
+               {
+                       base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
+                       VFS_WriteAt(disk->FD, base, disk->BlockSize, Buffer);
+                       Buffer += disk->BlockSize;
+                       retLen -= disk->BlockSize;
+                       block ++;
+               }
+               
+               // Write last block
+               base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
+               VFS_WriteAt(disk->FD, base, retLen, Buffer);
+               if(!bNewBlocks) return Length;  // Writing in only allocated space
+       }
+       else
+               base = Ext2_int_GetBlockAddr(disk, inode.i_block, allocSize/disk->BlockSize-1);
+       
+addBlocks:
+       Log_Notice("EXT2", "File extending is untested");
+       
+       // Allocate blocks and copy data to them
+       retLen = Length - (allocSize-Offset);
+       while( retLen > disk->BlockSize )
+       {
+               // Allocate a block
+               block = Ext2_int_AllocateBlock(disk, base/disk->BlockSize);
+               if(!block)      return Length - retLen;
+               // Add it to this inode
+               if( !Ext2_int_AppendBlock(disk, &inode, block) ) {
+                       Ext2_int_DeallocateBlock(disk, block);
+                       goto ret;
+               }
+               // Copy data to the node
+               base = block * disk->BlockSize;
+               VFS_WriteAt(disk->FD, base, disk->BlockSize, Buffer);
+               // Update pointer and size remaining
+               inode.i_size += disk->BlockSize;
+               Buffer += disk->BlockSize;
+               retLen -= disk->BlockSize;
+       }
+       // Last block :D
+       block = Ext2_int_AllocateBlock(disk, base/disk->BlockSize);
+       if(!block)      goto ret;
+       if( !Ext2_int_AppendBlock(disk, &inode, block) ) {
+               Ext2_int_DeallocateBlock(disk, block);
+               goto ret;
+       }
+       base = block * disk->BlockSize;
+       VFS_WriteAt(disk->FD, base, retLen, Buffer);
+       inode.i_size += retLen;
+       retLen = 0;
+
+ret:   // Makes sure the changes to the inode are committed
+       Ext2_int_WriteInode(disk, Node->Inode, &inode);
+       return Length - retLen;
+}
+
+/**
+ * \fn Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock)
+ * \brief Allocate a block from the best possible location
+ * \param Disk EXT2 Disk Information Structure
+ * \param PrevBlock    Previous block ID in the file
+ */
+Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock)
+{
+        int    bpg = Disk->SuperBlock.s_blocks_per_group;
+       Uint    blockgroup = PrevBlock / bpg;
+       Uint    bitmap[Disk->BlockSize/sizeof(Uint)];
+       Uint    bitsperblock = 8*Disk->BlockSize;
+        int    i, j = 0;
+       Uint    block;
+       
+       // Are there any free blocks?
+       if(Disk->SuperBlock.s_free_blocks_count == 0)   return 0;
+       
+       if(Disk->Groups[blockgroup].bg_free_blocks_count > 0)
+       {
+               // Search block group's bitmap
+               for(i = 0; i < bpg; i++)
+               {
+                       // Get the block in the bitmap block
+                       j = i & (bitsperblock-1);
+                       
+                       // Read in if needed
+                       if(j == 0) {
+                               VFS_ReadAt(
+                                       Disk->FD,
+                                       (Uint64)Disk->Groups[blockgroup].bg_block_bitmap + i / bitsperblock,
+                                       Disk->BlockSize,
+                                       bitmap
+                                       );
+                       }
+                       
+                       // Fast Check
+                       if( bitmap[j/32] == -1 ) {
+                               j = (j + 31) & ~31;
+                               continue;
+                       }
+                       
+                       // Is the bit set?
+                       if( bitmap[j/32] & (1 << (j%32)) )
+                               continue;
+                       
+                       // Ooh! We found one
+                       break;
+               }
+               if( i < bpg ) {
+                       Warning("[EXT2 ] Inconsistency detected, Group Free Block count is non-zero when no free blocks exist");
+                       goto    checkAll;       // Search the entire filesystem for a free block
+                       // Goto needed for neatness
+               }
+               
+               // Mark as used
+               bitmap[j/32] |= (1 << (j%32));
+               VFS_WriteAt(
+                       Disk->FD,
+                       (Uint64)Disk->Groups[blockgroup].bg_block_bitmap + i / bitsperblock,
+                       Disk->BlockSize,
+                       bitmap
+                       );
+               block = i;
+               Disk->Groups[blockgroup].bg_free_blocks_count --;
+               #if EXT2_UPDATE_WRITEBACK
+               //Ext2_int_UpdateBlockGroup(Disk, blockgroup);
+               #endif
+       }
+       else
+       {
+       checkAll:
+               Log_Warning("EXT2", "TODO - Implement using blocks outside the current block group");
+               return 0;
+       }
+       
+       // Reduce global count
+       Disk->SuperBlock.s_free_blocks_count --;
+       #if EXT2_UPDATE_WRITEBACK
+       Ext2_int_UpdateSuperblock(Disk);
+       #endif
+       
+       return block;
+}
+
+/**
+ * \brief Deallocates a block
+ */
+void Ext2_int_DeallocateBlock(tExt2_Disk *Disk, Uint32 Block)
+{
+}
+
+/**
+ * \brief Append a block to an inode
+ */
+int Ext2_int_AppendBlock(tExt2_Disk *Disk, tExt2_Inode *Inode, Uint32 Block)
+{
+        int    nBlocks;
+        int    dwPerBlock = Disk->BlockSize / 4;
+       Uint32  *blocks;
+       Uint32  id1, id2;
+       
+       nBlocks = (Inode->i_size + Disk->BlockSize - 1) / Disk->BlockSize;
+       
+       // Direct Blocks
+       if( nBlocks < 12 ) {
+               Inode->i_block[nBlocks] = Block;
+               return 0;
+       }
+       
+       blocks = malloc( Disk->BlockSize );
+       if(!blocks)     return 1;
+       
+       nBlocks -= 12;
+       // Single Indirect
+       if( nBlocks < dwPerBlock)
+       {
+               // Allocate/Get Indirect block
+               if( nBlocks == 0 ) {
+                       Inode->i_block[12] = Ext2_int_AllocateBlock(Disk, Inode->i_block[0]);
+                       if( !Inode->i_block[12] ) {
+                               free(blocks);
+                               return 1;
+                       }
+                       memset(blocks, 0, Disk->BlockSize); 
+               }
+               else
+                       VFS_ReadAt(Disk->FD, Inode->i_block[12]*Disk->BlockSize, Disk->BlockSize, blocks);
+               
+               blocks[nBlocks] = Block;
+               
+               VFS_WriteAt(Disk->FD, Inode->i_block[12]*Disk->BlockSize, Disk->BlockSize, blocks);
+               free(blocks);
+               return 0;
+       }
+       
+       nBlocks += dwPerBlock;
+       // Double Indirect
+       if( nBlocks < dwPerBlock*dwPerBlock )
+       {
+               // Allocate/Get Indirect block
+               if( nBlocks == 0 ) {
+                       Inode->i_block[13] = Ext2_int_AllocateBlock(Disk, Inode->i_block[0]);
+                       if( !Inode->i_block[13] ) {
+                               free(blocks);
+                               return 1;
+                       }
+                       memset(blocks, 0, Disk->BlockSize);
+               }
+               else
+                       VFS_ReadAt(Disk->FD, Inode->i_block[13]*Disk->BlockSize, Disk->BlockSize, blocks);
+               
+               // Allocate / Get Indirect lvl2 Block
+               if( nBlocks % dwPerBlock == 0 ) {
+                       id1 = Ext2_int_AllocateBlock(Disk, Inode->i_block[0]);
+                       if( !id1 ) {
+                               free(blocks);
+                               return 1;
+                       }
+                       blocks[nBlocks/dwPerBlock] = id1;
+                       // Write back indirect 1 block
+                       VFS_WriteAt(Disk->FD, Inode->i_block[13]*Disk->BlockSize, Disk->BlockSize, blocks);
+                       memset(blocks, 0, Disk->BlockSize);
+               }
+               else {
+                       id1 = blocks[nBlocks / dwPerBlock];
+                       VFS_ReadAt(Disk->FD, id1*Disk->BlockSize, Disk->BlockSize, blocks);
+               }
+               
+               blocks[nBlocks % dwPerBlock] = Block;
+               
+               VFS_WriteAt(Disk->FD, id1*Disk->BlockSize, Disk->BlockSize, blocks);
+               free(blocks);
+               return 0;
+       }
+       
+       nBlocks -= dwPerBlock*dwPerBlock;
+       // Triple Indirect
+       if( nBlocks < dwPerBlock*dwPerBlock*dwPerBlock )
+       {
+               // Allocate/Get Indirect block
+               if( nBlocks == 0 ) {
+                       Inode->i_block[14] = Ext2_int_AllocateBlock(Disk, Inode->i_block[0]);
+                       if( !Inode->i_block[14] ) {
+                               free(blocks);
+                               return 1;
+                       }
+                       memset(blocks, 0, Disk->BlockSize);
+               }
+               else
+                       VFS_ReadAt(Disk->FD, Inode->i_block[14]*Disk->BlockSize, Disk->BlockSize, blocks);
+               
+               // Allocate / Get Indirect lvl2 Block
+               if( (nBlocks/dwPerBlock) % dwPerBlock == 0 && nBlocks % dwPerBlock == 0 )
+               {
+                       id1 = Ext2_int_AllocateBlock(Disk, Inode->i_block[0]);
+                       if( !id1 ) {
+                               free(blocks);
+                               return 1;
+                       }
+                       blocks[nBlocks/dwPerBlock] = id1;
+                       // Write back indirect 1 block
+                       VFS_WriteAt(Disk->FD, Inode->i_block[14]*Disk->BlockSize, Disk->BlockSize, blocks);
+                       memset(blocks, 0, Disk->BlockSize);
+               }
+               else {
+                       id1 = blocks[nBlocks / (dwPerBlock*dwPerBlock)];
+                       VFS_ReadAt(Disk->FD, id1*Disk->BlockSize, Disk->BlockSize, blocks);
+               }
+               
+               // Allocate / Get Indirect Level 3 Block
+               if( nBlocks % dwPerBlock == 0 ) {
+                       id2 = Ext2_int_AllocateBlock(Disk, id1);
+                       if( !id2 ) {
+                               free(blocks);
+                               return 1;
+                       }
+                       blocks[(nBlocks/dwPerBlock)%dwPerBlock] = id2;
+                       // Write back indirect 1 block
+                       VFS_WriteAt(Disk->FD, id1*Disk->BlockSize, Disk->BlockSize, blocks);
+                       memset(blocks, 0, Disk->BlockSize);
+               }
+               else {
+                       id2 = blocks[(nBlocks/dwPerBlock)%dwPerBlock];
+                       VFS_ReadAt(Disk->FD, id2*Disk->BlockSize, Disk->BlockSize, blocks);
+               }
+               
+               blocks[nBlocks % dwPerBlock] = Block;
+               
+               VFS_WriteAt(Disk->FD, id2*Disk->BlockSize, Disk->BlockSize, blocks);
+               free(blocks);
+               return 0;
+       }
+       
+       Warning("[EXT2 ] Inode %i cannot have a block appended to it, all indirects used");
+       free(blocks);
+       return 1;
+}
diff --git a/Modules/Filesystems/FAT/Makefile b/Modules/Filesystems/FAT/Makefile
new file mode 100644 (file)
index 0000000..dfa290b
--- /dev/null
@@ -0,0 +1,7 @@
+#
+#
+
+OBJ = fat.o
+NAME = FAT
+
+-include ../Makefile.tpl
diff --git a/Modules/Filesystems/FAT/fat.c b/Modules/Filesystems/FAT/fat.c
new file mode 100644 (file)
index 0000000..3ec2a5f
--- /dev/null
@@ -0,0 +1,1389 @@
+/*\r
+ * Acess 2\r
+ * FAT12/16/32 Driver Version (Incl LFN)\r
+ * \r
+ * NOTE: This driver will only support _reading_ long file names, not\r
+ * writing. I don't even know why i'm adding write-support. FAT sucks.\r
+ * \r
+ * Known Bugs:\r
+ * - LFN Is buggy in FAT_ReadDir\r
+ */\r
+/**\r
+ * \todo Implement changing of the parent directory when a file is written to\r
+ * \todo Implement file creation / deletion\r
+ */\r
+#define DEBUG  1\r
+#define VERBOSE        1\r
+\r
+#define CACHE_FAT      1       //!< Caches the FAT in memory\r
+#define USE_LFN                0       //!< Enables the use of Long File Names\r
+#define        SUPPORT_WRITE   0\r
+\r
+#include <acess.h>\r
+#include <modules.h>\r
+#include <vfs.h>\r
+#include "fs_fat.h"\r
+\r
+#define FAT_FLAG_DIRTY 0x10000\r
+#define FAT_FLAG_DELETE        0x20000\r
+\r
+// === TYPES ===\r
+#if USE_LFN\r
+typedef struct s_lfncache\r
+{\r
+       Uint    Inode;\r
+       tFAT_VolInfo    *Disk;\r
+        int    id;\r
+       char    Name[256];\r
+       struct s_lfncache       *Next;\r
+}      t_lfncache;\r
+#endif\r
+\r
+// === PROTOTYPES ===\r
+ int   FAT_Install(char **Arguments);\r
+tVFS_Node      *FAT_InitDevice(char *device, char **options);\r
+void   FAT_Unmount(tVFS_Node *Node);\r
+\r
+Uint32 FAT_int_GetFatValue(tFAT_VolInfo *Disk, Uint32 Cluster);\r
+Uint32 FAT_int_AllocateCluster(tFAT_VolInfo *Disk, Uint32 Previous);\r
+\r
+void   FAT_int_ReadCluster(tFAT_VolInfo *Disk, Uint32 Cluster, int Length, void *Buffer);\r
+Uint64 FAT_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);\r
+#if SUPPORT_WRITE\r
+void   FAT_int_WriteCluster(tFAT_VolInfo *Disk, Uint32 Cluster, void *Buffer);\r
+Uint64 FAT_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);\r
+#endif\r
+\r
+char   *FAT_ReadDir(tVFS_Node *Node, int ID);\r
+tVFS_Node      *FAT_FindDir(tVFS_Node *Node, char *Name);\r
+ int   FAT_Mknod(tVFS_Node *Node, char *Name, Uint Flags);\r
+ int   FAT_Relink(tVFS_Node *node, char *OldName, char *NewName);\r
+void   FAT_CloseFile(tVFS_Node *node);\r
+\r
+// === Options ===\r
+ int   giFAT_MaxCachedClusters = 1024*512/4;\r
+\r
+// === SEMI-GLOBALS ===\r
+MODULE_DEFINE(0, (0<<8)|50 /*v0.50*/, VFAT, FAT_Install, NULL, NULL);\r
+tFAT_VolInfo   gFAT_Disks[8];\r
+ int   giFAT_PartCount = 0;\r
+#if USE_LFN\r
+t_lfncache     *fat_lfncache;\r
+#endif\r
+tVFS_Driver    gFAT_FSInfo = {"fat", 0, FAT_InitDevice, FAT_Unmount, NULL};\r
+\r
+// === CODE ===\r
+/**\r
+ * \fn int FAT_Install(char **Arguments)\r
+ * \brief \r
+ */\r
+int FAT_Install(char **Arguments)\r
+{\r
+       VFS_AddDriver( &gFAT_FSInfo );\r
+       return MODULE_ERR_OK;\r
+}\r
+\r
+/**\r
+ * \fn tVFS_Node *FAT_InitDevice(char *Device, char **Options)\r
+ * \brief Reads the boot sector of a disk and prepares the structures for it\r
+ */\r
+tVFS_Node *FAT_InitDevice(char *Device, char **Options)\r
+{\r
+       fat_bootsect *bs;\r
+        int    i;\r
+       Uint32  FATSz, RootDirSectors, TotSec;\r
+       tVFS_Node       *node = NULL;\r
+       tFAT_VolInfo    *diskInfo = &gFAT_Disks[giFAT_PartCount];\r
+       \r
+       // Temporary Pointer\r
+       bs = &diskInfo->bootsect;\r
+       \r
+       //Open device and read boot sector\r
+       diskInfo->fileHandle = VFS_Open(Device, VFS_OPENFLAG_READ|VFS_OPENFLAG_WRITE);\r
+       if(diskInfo->fileHandle == -1) {\r
+               Log_Notice("FAT", "Unable to open device '%s'", Device);\r
+               return NULL;\r
+       }\r
+       \r
+       VFS_ReadAt(diskInfo->fileHandle, 0, 512, bs);\r
+       \r
+       if(bs->bps == 0 || bs->spc == 0) {\r
+               Log_Notice("FAT", "Error in FAT Boot Sector");\r
+               return NULL;\r
+       }\r
+       \r
+       // FAT Type Determining\r
+       // - From Microsoft FAT Specifcation\r
+       RootDirSectors = ((bs->files_in_root*32) + (bs->bps - 1)) / bs->bps;\r
+       \r
+       if(bs->fatSz16 != 0)            FATSz = bs->fatSz16;\r
+       else                                    FATSz = bs->spec.fat32.fatSz32;\r
+       \r
+       if(bs->totalSect16 != 0)                TotSec = bs->totalSect16;\r
+       else                                            TotSec = bs->totalSect32;\r
+       \r
+       diskInfo->ClusterCount = (TotSec - (bs->resvSectCount + (bs->fatCount * FATSz) + RootDirSectors)) / bs->spc;\r
+       \r
+       if(diskInfo->ClusterCount < 4085)\r
+               diskInfo->type = FAT12;\r
+       else if(diskInfo->ClusterCount < 65525)\r
+               diskInfo->type = FAT16;\r
+       else\r
+               diskInfo->type = FAT32;\r
+       \r
+       #if VERBOSE\r
+       {\r
+               char    *sFatType, *sSize;\r
+               Uint    iSize = diskInfo->ClusterCount * bs->spc * bs->bps / 1024;\r
+               \r
+               switch(diskInfo->type)\r
+               {\r
+               case FAT12:     sFatType = "FAT12";     break;\r
+               case FAT16:     sFatType = "FAT16";     break;\r
+               case FAT32:     sFatType = "FAT32";     break;\r
+               default:        sFatType = "UNKNOWN";   break;\r
+               }\r
+               if(iSize <= 2*1024) {\r
+                       sSize = "KiB";\r
+               }\r
+               else if(iSize <= 2*1024*1024) {\r
+                       sSize = "MiB";\r
+                       iSize >>= 10;\r
+               }\r
+               else {\r
+                       sSize = "GiB";\r
+                       iSize >>= 20;\r
+               }\r
+               Log_Notice("FAT", "'%s' %s, %i %s", Device, sFatType, iSize, sSize);\r
+       }\r
+       #endif\r
+       \r
+       // Get Name\r
+       if(diskInfo->type == FAT32) {\r
+               for(i=0;i<11;i++)\r
+                       diskInfo->name[i] = (bs->spec.fat32.label[i] == ' ' ? '\0' : bs->spec.fat32.label[i]);\r
+       }\r
+       else {\r
+               for(i=0;i<11;i++)\r
+                       diskInfo->name[i] = (bs->spec.fat16.label[i] == ' ' ? '\0' : bs->spec.fat16.label[i]);\r
+       }\r
+       diskInfo->name[11] = '\0';\r
+       \r
+       // Compute Root directory offset\r
+       if(diskInfo->type == FAT32)\r
+               diskInfo->rootOffset = bs->spec.fat32.rootClust;\r
+       else\r
+               diskInfo->rootOffset = (FATSz * bs->fatCount) / bs->spc;\r
+       \r
+       diskInfo->firstDataSect = bs->resvSectCount + (bs->fatCount * FATSz) + RootDirSectors;\r
+       \r
+       //Allow for Caching the FAT\r
+       #if CACHE_FAT\r
+       if( diskInfo->ClusterCount <= giFAT_MaxCachedClusters )\r
+       {\r
+               Uint32  Ofs;\r
+               diskInfo->FATCache = (Uint32*)malloc(sizeof(Uint32)*diskInfo->ClusterCount);\r
+               if(diskInfo->FATCache == NULL) {\r
+                       Log_Warning("FAT", "Heap Exhausted");\r
+                       return NULL;\r
+               }\r
+               Ofs = bs->resvSectCount*512;\r
+               if(diskInfo->type == FAT12)\r
+               {\r
+                       Uint32  val;\r
+                        int    j;\r
+                       char    buf[1536];\r
+                       for(i = 0; i < diskInfo->ClusterCount/2; i++) {\r
+                               j = i & 511;    //%512\r
+                               if( j == 0 ) {\r
+                                       VFS_ReadAt(diskInfo->fileHandle, Ofs, 3*512, buf);\r
+                                       Ofs += 3*512;\r
+                               }\r
+                               val = *((int*)(buf+j*3));\r
+                               diskInfo->FATCache[i*2] = val & 0xFFF;\r
+                               diskInfo->FATCache[i*2+1] = (val>>12) & 0xFFF;\r
+                       }\r
+               }\r
+               else if(diskInfo->type == FAT16)\r
+               {\r
+                       Uint16  buf[256];\r
+                       for(i=0;i<diskInfo->ClusterCount;i++) {\r
+                               if( (i & 255) == 0 ) {\r
+                                       VFS_ReadAt(diskInfo->fileHandle, Ofs, 512, buf);\r
+                                       Ofs += 512;\r
+                               }\r
+                               diskInfo->FATCache[i] = buf[i&255];\r
+                       }\r
+               }\r
+               else if(diskInfo->type == FAT32)\r
+               {\r
+                       Uint32  buf[128];\r
+                       for(i=0;i<diskInfo->ClusterCount;i++) {\r
+                               if( (i & 127) == 0 ) {\r
+                                       VFS_ReadAt(diskInfo->fileHandle, Ofs, 512, buf);\r
+                                       Ofs += 512;\r
+                               }\r
+                               diskInfo->FATCache[i] = buf[i&127];\r
+                       }\r
+               }\r
+               LOG("FAT Fully Cached");\r
+       }\r
+       #endif /*CACHE_FAT*/\r
+       \r
+       diskInfo->BytesPerCluster = bs->spc * bs->bps;\r
+       \r
+       // Initalise inode cache for filesystem\r
+       diskInfo->inodeHandle = Inode_GetHandle();\r
+       LOG("Inode Cache handle is %i", diskInfo->inodeHandle);\r
+       \r
+       // == VFS Interface\r
+       node = &diskInfo->rootNode;\r
+       //node->Size = bs->files_in_root;\r
+       node->Size = -1;\r
+       node->Inode = diskInfo->rootOffset;     // 0:31 - Cluster, 32:63 - Parent Directory Cluster\r
+       node->ImplPtr = diskInfo;       // Disk info pointer\r
+       node->ImplInt = 0;      // 0:15 - Directory Index, 16: Dirty Flag, 17: Deletion Flag\r
+       \r
+       node->ReferenceCount = 1;\r
+       \r
+       node->UID = 0;  node->GID = 0;\r
+       node->NumACLs = 1;\r
+       node->ACLs = &gVFS_ACL_EveryoneRWX;\r
+       node->Flags = VFS_FFLAG_DIRECTORY;\r
+       node->CTime = node->MTime = node->ATime = now();\r
+       \r
+       node->Read = node->Write = NULL;\r
+       node->ReadDir = FAT_ReadDir;\r
+       node->FindDir = FAT_FindDir;\r
+       #if SUPPORT_WRITE\r
+       node->Relink = FAT_Relink;\r
+       node->MkNod = FAT_Mknod;\r
+       #else\r
+       node->Relink = NULL;\r
+       node->MkNod = NULL;\r
+       #endif\r
+       //node->Close = FAT_Unmount;\r
+       \r
+       giFAT_PartCount ++;\r
+       return node;\r
+}\r
+\r
+/**\r
+ * \brief Closes a mount and marks it as free\r
+ * \param Node Mount Root\r
+ * \r
+ * \todo Remove FAT Cache\r
+ * \todo Clear LFN Cache\r
+ * \todo Check that all files are closed and flushed\r
+ */\r
+void FAT_Unmount(tVFS_Node *Node)\r
+{\r
+       tFAT_VolInfo    *disk = Node->ImplPtr;\r
+       \r
+       // Close Disk Handle\r
+       VFS_Close( disk->fileHandle );\r
+       // Clear Node Cache\r
+       Inode_ClearCache(disk->inodeHandle);\r
+       // Mark as unused\r
+       disk->fileHandle = -2;\r
+       return;\r
+}\r
+\r
+/**\r
+ * \brief Converts an offset in a file into a disk address\r
+ * \param Node File (or directory) node\r
+ * \param Offset       Offset in the file\r
+ * \param Addr Return Address\r
+ * \param Cluster      Set to the current cluster (or the last one if \a Offset\r
+ *                  is past EOC) - Not touched if the node is the root\r
+ *                  directory.\r
+ * \return Zero on success, non-zero on error\r
+ */\r
+int FAT_int_GetAddress(tVFS_Node *Node, Uint64 Offset, Uint64 *Addr, Uint32 *Cluster)\r
+{\r
+       Uint32  cluster;\r
+       Uint64  addr;\r
+        int    skip;\r
+       tFAT_VolInfo    *disk = Node->ImplPtr;\r
+       \r
+       ENTER("pNode XOffset", Node, Offset);\r
+       \r
+       cluster = Node->Inode & 0xFFFFFFFF;     // Cluster ID\r
+       LOG("cluster = %08x", cluster);\r
+       \r
+       // Do Cluster Skip\r
+       // - Pre FAT32 had a reserved area for the root.\r
+       if( disk->type == FAT32 || cluster != disk->rootOffset )\r
+       {\r
+               skip = Offset / disk->BytesPerCluster;\r
+               LOG("skip = %i", skip);\r
+               // Skip previous clusters\r
+               for(; skip-- ; )\r
+               {\r
+                       if(Cluster)     *Cluster = cluster;\r
+                       cluster = FAT_int_GetFatValue(disk, cluster);\r
+                       // Check for end of cluster chain\r
+                       if(cluster == -1) {     LEAVE('i', 1);  return 1;}\r
+               }\r
+               if(Cluster)     *Cluster = cluster;\r
+       }\r
+       \r
+       // Bounds Checking (Used to spot corruption)\r
+       if(cluster > disk->ClusterCount + 2)\r
+       {\r
+               Log_Warning("FAT", "Cluster ID is over cluster count (0x%x>0x%x)",\r
+                       cluster, disk->ClusterCount+2);\r
+               LEAVE('i', 1);\r
+               return 1;\r
+       }\r
+       \r
+       // Compute Offsets\r
+       // - Pre FAT32 cluster base (in sectors)\r
+       if( cluster == disk->rootOffset && disk->type != FAT32 ) {\r
+               addr = disk->bootsect.resvSectCount * disk->bootsect.bps;\r
+               addr += cluster * disk->BytesPerCluster;\r
+       }\r
+       else {\r
+               addr = disk->firstDataSect * disk->bootsect.bps;\r
+               addr += (cluster - 2) * disk->BytesPerCluster;\r
+       }\r
+       addr += Offset % disk->BytesPerCluster;\r
+       \r
+       LOG("addr = 0x%08x", addr);\r
+       *Addr = addr;\r
+       LEAVE('i', 0);\r
+       return 0;\r
+}\r
+\r
+/*\r
+ * ====================\r
+ *   FAT Manipulation\r
+ * ====================\r
+ */\r
+/**\r
+ * \fn Uint32 FAT_int_GetFatValue(tFAT_VolInfo *Disk, Uint32 cluster)\r
+ * \brief Fetches a value from the FAT\r
+ */\r
+Uint32 FAT_int_GetFatValue(tFAT_VolInfo *Disk, Uint32 cluster)\r
+{\r
+       Uint32  val = 0;\r
+       Uint32  ofs;\r
+       ENTER("pDisk xCluster", Disk, cluster);\r
+       LOCK( &Disk->lFAT );\r
+       #if CACHE_FAT\r
+       if( Disk->ClusterCount <= giFAT_MaxCachedClusters )\r
+       {\r
+               val = Disk->FATCache[cluster];\r
+               if(Disk->type == FAT12 && val == EOC_FAT12)     val = -1;\r
+               if(Disk->type == FAT16 && val == EOC_FAT16)     val = -1;\r
+               if(Disk->type == FAT32 && val == EOC_FAT32)     val = -1;\r
+       }\r
+       else\r
+       {\r
+       #endif\r
+               ofs = Disk->bootsect.resvSectCount*512;\r
+               if(Disk->type == FAT12) {\r
+                       VFS_ReadAt(Disk->fileHandle, ofs+(cluster>>1)*3, 3, &val);\r
+                       val = (cluster&1 ? val&0xFFF : val>>12);\r
+                       if(val == EOC_FAT12)    val = -1;\r
+               } else if(Disk->type == FAT16) {\r
+                       VFS_ReadAt(Disk->fileHandle, ofs+cluster*2, 2, &val);\r
+                       if(val == EOC_FAT16)    val = -1;\r
+               } else {\r
+                       VFS_ReadAt(Disk->fileHandle, ofs+cluster*4, 4, &val);\r
+                       if(val == EOC_FAT32)    val = -1;\r
+               }\r
+       #if CACHE_FAT\r
+       }\r
+       #endif /*CACHE_FAT*/\r
+       RELEASE( &Disk->lFAT );\r
+       LEAVE('x', val);\r
+       return val;\r
+}\r
+\r
+#if SUPPORT_WRITE\r
+/**\r
+ * \brief Allocate a new cluster\r
+ */\r
+Uint32 FAT_int_AllocateCluster(tFAT_VolInfo *Disk, Uint32 Previous)\r
+{\r
+       Uint32  ret = Previous;\r
+       #if CACHE_FAT\r
+       if( Disk->ClusterCount <= giFAT_MaxCachedClusters )\r
+       {\r
+               Uint32  eoc;\r
+               \r
+               LOCK(Disk->lFAT);\r
+               for(ret = Previous; ret < Disk->ClusterCount; ret++)\r
+               {\r
+                       if(Disk->FATCache[ret] == 0)\r
+                               goto append;\r
+               }\r
+               for(ret = 0; ret < Previous; ret++)\r
+               {\r
+                       if(Disk->FATCache[ret] == 0)\r
+                               goto append;\r
+               }\r
+               \r
+               RELEASE(Disk->lFAT);\r
+               return 0;\r
+       \r
+       append:\r
+               switch(Disk->type)\r
+               {\r
+               case FAT12:     eoc = EOC_FAT12;        break;\r
+               case FAT16:     eoc = EOC_FAT16;        break;\r
+               case FAT32:     eoc = EOC_FAT32;        break;\r
+               default:        return 0;\r
+               }\r
+               \r
+               Disk->FATCache[ret] = eoc;\r
+               Disk->FATCache[Previous] = ret;\r
+               \r
+               RELEASE(Disk->lFAT);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+       #endif\r
+               Uint32  val;\r
+               Uint32  ofs = Disk->bootsect.resvSectCount*512;\r
+               Log_Warning("FAT", "TODO: Implement cluster allocation with non cached FAT");\r
+               return 0;\r
+               \r
+               switch(Disk->type)\r
+               {\r
+               case FAT12:\r
+                       VFS_ReadAt(Disk->fileHandle, ofs+(Previous>>1)*3, 3, &val);\r
+                       if( Previous & 1 ) {\r
+                               val &= 0xFFF000;\r
+                               val |= ret;\r
+                       }\r
+                       else {\r
+                               val &= 0xFFF;\r
+                               val |= ret<<12;\r
+                       }\r
+                       VFS_WriteAt(Disk->fileHandle, ofs+(Previous>>1)*3, 3, &val);\r
+                       \r
+                       VFS_ReadAt(Disk->fileHandle, ofs+(ret>>1)*3, 3, &val);\r
+                       if( Cluster & 1 ) {\r
+                               val &= 0xFFF000;\r
+                               val |= eoc;\r
+                       }\r
+                       else {\r
+                               val &= 0x000FFF;\r
+                               val |= eoc<<12;\r
+                       }\r
+                       VFS_WriteAt(Disk->fileHandle, ofs+(ret>>1)*3, 3, &val);\r
+                       break;\r
+               case FAT16:\r
+                       VFS_ReadAt(Disk->fileHandle, ofs+Previous*2, 2, &ret);\r
+                       VFS_WriteAt(Disk->fileHandle, ofs+ret*2, 2, &eoc);\r
+                       break;\r
+               case FAT32:\r
+                       VFS_ReadAt(Disk->fileHandle, ofs+Previous*4, 4, &ret);\r
+                       VFS_WriteAt(Disk->fileHandle, ofs+ret*4, 4, &eoc);\r
+                       break;\r
+               }\r
+               return ret;\r
+       #if CACHE_FAT\r
+       }\r
+       #endif\r
+}\r
+\r
+/**\r
+ * \brief Free's a cluster\r
+ * \return The original contents of the cluster\r
+ */\r
+Uint32 FAT_int_FreeCluster(tFAT_VolInfo *Disk, Uint32 Cluster)\r
+{\r
+       Uint32  ret;\r
+       #if CACHE_FAT\r
+       if( Disk->ClusterCount <= giFAT_MaxCachedClusters )\r
+       {\r
+               LOCK(Disk->lFAT);\r
+               \r
+               ret = Disk->FATCache[Cluster];\r
+               Disk->FATCache[Cluster] = 0;\r
+               \r
+               RELEASE(Disk->lFAT);\r
+       }\r
+       else\r
+       {\r
+       #endif\r
+               Uint32  val;\r
+               Uint32  ofs = Disk->bootsect.resvSectCount*512;\r
+               LOCK(Disk->lFAT);\r
+               switch(Disk->type)\r
+               {\r
+               case FAT12:\r
+                       VFS_ReadAt(Disk->fileHandle, ofs+(Cluster>>1)*3, 3, &val);\r
+                       if( Cluster & 1 ) {\r
+                               ret = val & 0xFFF0000;\r
+                               val &= 0xFFF;\r
+                       }\r
+                       else {\r
+                               ret = val & 0xFFF;\r
+                               val &= 0xFFF000;\r
+                       }\r
+                       VFS_WriteAt(Disk->fileHandle, ofs+(Previous>>1)*3, 3, &val);\r
+                       break;\r
+               case FAT16:\r
+                       VFS_ReadAt(Disk->fileHandle, ofs+Previous*2, 2, &ret);\r
+                       val = 0;\r
+                       VFS_WriteAt(Disk->fileHandle, ofs+Cluster*2, 2, &val);\r
+                       break;\r
+               case FAT32:\r
+                       VFS_ReadAt(Disk->fileHandle, ofs+Previous*4, 4, &ret);\r
+                       val = 0;\r
+                       VFS_WriteAt(Disk->fileHandle, ofs+Cluster*2, 2, &val);\r
+                       break;\r
+               }\r
+               RELEASE(Disk->lFAT);\r
+       #if CACHE_FAT\r
+       }\r
+       #endif\r
+       if(Disk->type == FAT12 && ret == EOC_FAT12)     ret = -1;\r
+       if(Disk->type == FAT16 && ret == EOC_FAT16)     ret = -1;\r
+       if(Disk->type == FAT32 && ret == EOC_FAT32)     ret = -1;\r
+       return ret;\r
+}\r
+#endif\r
+\r
+/*\r
+ * ====================\r
+ *      Cluster IO\r
+ * ====================\r
+ */\r
+/**\r
+ * \brief Read a cluster\r
+ */\r
+void FAT_int_ReadCluster(tFAT_VolInfo *Disk, Uint32 Cluster, int Length, void *Buffer)\r
+{\r
+       ENTER("pDisk xCluster iLength pBuffer", Disk, Cluster, Length, Buffer);\r
+       //Log("Cluster = %i (0x%x)", Cluster, Cluster);\r
+       VFS_ReadAt(\r
+               Disk->fileHandle,\r
+               (Disk->firstDataSect + (Cluster-2)*Disk->bootsect.spc )\r
+                       * Disk->bootsect.bps,\r
+               Length,\r
+               Buffer\r
+               );\r
+       LEAVE('-');\r
+}\r
+\r
+/* ====================\r
+ *       File IO\r
+ * ====================\r
+ */\r
+/**\r
+ * \fn Uint64 FAT_Read(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer)\r
+ * \brief Reads data from a specified file\r
+ */\r
+Uint64 FAT_Read(tVFS_Node *Node, Uint64 offset, Uint64 length, void *buffer)\r
+{\r
+        int    preSkip, count;\r
+        int    i, cluster, pos;\r
+        int    bpc;\r
+       void    *tmpBuf;\r
+       tFAT_VolInfo    *disk = Node->ImplPtr;\r
+       \r
+       ENTER("pNode Xoffset Xlength pbuffer", Node, offset, length, buffer);\r
+       \r
+       // Calculate and Allocate Bytes Per Cluster\r
+       bpc = disk->BytesPerCluster;\r
+       tmpBuf = (void*) malloc(bpc);\r
+       if( !tmpBuf )   return 0;\r
+       \r
+       // Cluster is stored in Inode Field\r
+       cluster = Node->Inode & 0xFFFFFFFF;\r
+       \r
+       // Sanity Check offset\r
+       if(offset > Node->Size) {\r
+               LOG("Reading past EOF (%i > %i)", offset, Node->Size);\r
+               LEAVE('i', 0);\r
+               return 0;\r
+       }\r
+       // Clamp Size\r
+       if(offset + length > Node->Size) {\r
+               LOG("Reading past EOF (%lli + %lli > %lli), clamped to %lli",\r
+                       offset, length, Node->Size, Node->Size - offset);\r
+               length = Node->Size - offset;\r
+       }\r
+       \r
+       // Single Cluster including offset\r
+       if(length + offset < bpc)\r
+       {\r
+               FAT_int_ReadCluster(disk, cluster, bpc, tmpBuf);\r
+               memcpy( buffer, (void*)( tmpBuf + offset%bpc ), length );\r
+               free(tmpBuf);\r
+               LEAVE('i', 1);\r
+               return length;\r
+       }\r
+       \r
+       #if 0\r
+       if( FAT_int_GetAddress(Node, offset, &addr) )\r
+       {\r
+               Log_Warning("FAT", "Offset is past end of cluster chain mark");\r
+               LEAVE('i', 0);\r
+               return 0;\r
+       }\r
+       #endif\r
+       \r
+       preSkip = offset / bpc;\r
+       \r
+       //Skip previous clusters\r
+       for(i=preSkip;i--;)     {\r
+               cluster = FAT_int_GetFatValue(disk, cluster);\r
+               if(cluster == -1) {\r
+                       Log_Warning("FAT", "Offset is past end of cluster chain mark");\r
+                       LEAVE('i', 0);\r
+                       return 0;\r
+               }\r
+       }\r
+       \r
+       // Get Count of Clusters to read\r
+       count = ((offset%bpc+length) / bpc) + 1;\r
+       \r
+       // Get buffer Position after 1st cluster\r
+       pos = bpc - offset%bpc;\r
+       \r
+       // Read 1st Cluster\r
+       FAT_int_ReadCluster(disk, cluster, bpc, tmpBuf);\r
+       memcpy(\r
+               buffer,\r
+               (void*)( tmpBuf + (bpc-pos) ),\r
+               (pos < length ? pos : length)\r
+               );\r
+       \r
+       if (count == 1) {\r
+               free(tmpBuf);\r
+               LEAVE('i', 1);\r
+               return length;\r
+       }\r
+       \r
+       cluster = FAT_int_GetFatValue(disk, cluster);\r
+       \r
+       #if DEBUG\r
+       LOG("pos = %i", pos);\r
+       LOG("Reading the rest of the clusters");\r
+       #endif\r
+       \r
+       \r
+       // Read the rest of the cluster data\r
+       for( i = 1; i < count-1; i++ )\r
+       {\r
+               FAT_int_ReadCluster(disk, cluster, bpc, tmpBuf);\r
+               memcpy((void*)(buffer+pos), tmpBuf, bpc);\r
+               pos += bpc;\r
+               cluster = FAT_int_GetFatValue(disk, cluster);\r
+               if(cluster == -1) {\r
+                       Warning("FAT_Read - Read past End of Cluster Chain");\r
+                       free(tmpBuf);\r
+                       LEAVE('i', 0);\r
+                       return 0;\r
+               }\r
+       }\r
+       \r
+       FAT_int_ReadCluster(disk, cluster, bpc, tmpBuf);\r
+       memcpy((void*)(buffer+pos), tmpBuf, length-pos);\r
+       \r
+       #if DEBUG\r
+       LOG("Free tmpBuf(0x%x) and Return", tmpBuf);\r
+       #endif\r
+       \r
+       free(tmpBuf);\r
+       LEAVE('X', length);\r
+       return length;\r
+}\r
+\r
+#if SUPPORT_WRITE\r
+/**\r
+ * \brief Write a cluster to disk\r
+ */\r
+void FAT_int_WriteCluster(tFAT_VolInfo *Disk, Uint32 Cluster, void *Buffer)\r
+{\r
+       ENTER("pDisk xCluster pBuffer", Disk, Cluster, Buffer);\r
+       VFS_ReadAt(\r
+               Disk->fileHandle,\r
+               (Disk->firstDataSect + (Cluster-2)*Disk->bootsect.spc )\r
+                       * Disk->bootsect.bps,\r
+               Disk->BytesPerCluster,\r
+               Buffer\r
+               );\r
+       LEAVE('-');\r
+}\r
+\r
+/**\r
+ * \brief Write to a file\r
+ * \param Node File Node\r
+ * \param Offset       Offset within file\r
+ * \param Length       Size of data to write\r
+ * \param Buffer       Data source\r
+ */\r
+Uint64 FAT_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)\r
+{\r
+       tFAT_VolInfo    *disk = Node->ImplPtr;\r
+       void    *tmpBuf;\r
+        int    remLength = Length;\r
+       Uint32  cluster, tmpCluster;\r
+        int    bNewCluster = 0;\r
+       \r
+       if(Offset > Node->Size) return 0;\r
+       \r
+       // Seek Clusters\r
+       cluster = Node->Inode & 0xFFFFFFFF;\r
+       while( Offset > disk->BytesPerCluster )\r
+       {\r
+               cluster = FAT_int_GetFatValue( disk, cluster );\r
+               if(cluster == -1) {\r
+                       Log_Warning("FAT", "EOC Unexpectedly Reached");\r
+                       return 0;\r
+               }\r
+               Offset -= disk->BytesPerCluster;\r
+       }\r
+       if( Offset == disk->BytesPerCluster )\r
+       {\r
+               Uint32  tmp = FAT_int_AllocateCluster(disk, cluster);\r
+               if(!tmp)        return 0;\r
+               cluster = tmp;\r
+               Offset -= disk->BytesPerCluster;\r
+       }\r
+       \r
+       if( Offset + Length < disk->BytesPerCluster )\r
+       {\r
+               tmpBuf = malloc( disk->BytesPerCluster );\r
+               \r
+               // Read-Modify-Write\r
+               FAT_int_ReadCluster( disk, cluster, disk->BytesPerCluster, tmpBuf );\r
+               memcpy( tmpBuf + Offset, Buffer, Length );\r
+               FAT_int_WriteCluster( disk, cluster, tmpBuf );\r
+               \r
+               free(tmpBuf);\r
+               return Length;\r
+       }\r
+       \r
+       // Clean up changes within a cluster\r
+       if( Offset )\r
+       {\r
+               tmpBuf = malloc( disk->BytesPerCluster );\r
+               \r
+               // Read-Modify-Write\r
+               FAT_int_ReadCluster( disk, cluster, disk->BytesPerCluster, tmpBuf );\r
+               memcpy( tmpBuf + Offset, Buffer, disk->BytesPerCluster - Offset );\r
+               FAT_int_WriteCluster( disk, cluster, tmpBuf );\r
+               \r
+               free(tmpBuf);\r
+               \r
+               remLength -= disk->BytesPerCluster - Offset;\r
+               Buffer += disk->BytesPerCluster - Offset;\r
+               \r
+               // Get next cluster (allocating if needed)\r
+               tmpCluster = FAT_int_GetFatValue(disk, cluster);\r
+               if(tmpCluster == -1) {\r
+                       tmpCluster = FAT_int_AllocateCluster(disk, cluster);\r
+                       if( tmpCluster == 0 ) {\r
+                               return Length - remLength;\r
+                       }\r
+               }\r
+               cluster = tmpCluster;\r
+       }\r
+       \r
+       while( remLength > disk->BytesPerCluster )\r
+       {\r
+               FAT_int_WriteCluster( disk, cluster, Buffer );\r
+               Buffer += disk->BytesPerCluster;\r
+               \r
+               // Get next cluster (allocating if needed)\r
+               tmpCluster = FAT_int_GetFatValue(disk, cluster);\r
+               if(tmpCluster == -1) {\r
+                       bNewCluster = 1;\r
+                       tmpCluster = FAT_int_AllocateCluster(disk, cluster);\r
+                       if( tmpCluster == 0 ) {\r
+                               return Length - remLength;\r
+                       }\r
+               }\r
+               cluster = tmpCluster;\r
+       }\r
+       \r
+       // Finish off\r
+       tmpBuf = malloc( disk->BytesPerCluster );\r
+       if( bNewCluster )\r
+               memset(tmpBuf, 0, disk->BytesPerCluster);\r
+       else\r
+               FAT_int_ReadCluster( disk, cluster, disk->BytesPerCluster, tmpBuf );\r
+       memcpy( tmpBuf, Buffer, remLength );\r
+       FAT_int_WriteCluster( disk, cluster, tmpBuf );\r
+       free( tmpBuf );\r
+       \r
+       return Length;\r
+}\r
+#endif\r
+\r
+/* ====================\r
+ *  File Names & Nodes\r
+ * ====================\r
+ */\r
+/**\r
+ * \fn void FAT_int_ProperFilename(char *dest, char *src)\r
+ * \brief Converts a FAT directory entry name into a proper filename\r
+ */\r
+void FAT_int_ProperFilename(char *dest, char *src)\r
+{\r
+        int    a, b;\r
+       \r
+       for( a = 0; a < 8; a++) {\r
+               if(src[a] == ' ')       break;\r
+               dest[a] = src[a];\r
+       }\r
+       b = a;\r
+       a = 8;\r
+       if(src[8] != ' ')\r
+               dest[b++] = '.';\r
+       for( ; a < 11; a++, b++)        {\r
+               if(src[a] == ' ')       break;\r
+               dest[b] = src[a];\r
+       }\r
+       dest[b] = '\0';\r
+       #if DEBUG\r
+       //LOG("dest='%s'", dest);\r
+       #endif\r
+}\r
+\r
+/**\r
+ * \fn char *FAT_int_CreateName(fat_filetable *ft, char *LongFileName)\r
+ * \brief Converts either a LFN or a 8.3 Name into a proper name\r
+ */\r
+char *FAT_int_CreateName(fat_filetable *ft, char *LongFileName)\r
+{\r
+       char    *ret;\r
+       ENTER("pft sLongFileName", ft, LongFileName);\r
+       #if USE_LFN\r
+       if(LongFileName && LongFileName[0] != '\0')\r
+       {       \r
+               ret = strdup(LongFileName);\r
+       }\r
+       else\r
+       {\r
+       #endif\r
+               ret = (char*) malloc(13);\r
+               memset(ret, 13, '\0');\r
+               FAT_int_ProperFilename(ret, ft->name);\r
+       #if USE_LFN\r
+       }\r
+       #endif\r
+       LEAVE('s', ret);\r
+       return ret;\r
+}\r
+\r
+/**\r
+ * \fn tVFS_Node *FAT_int_CreateNode(tVFS_Node *parent, fat_filetable *ft)\r
+ * \brief Creates a tVFS_Node structure for a given file entry\r
+ */\r
+tVFS_Node *FAT_int_CreateNode(tVFS_Node *Parent, fat_filetable *Entry, int Pos)\r
+{\r
+       tVFS_Node       node = {0};\r
+       tVFS_Node       *ret;\r
+       tFAT_VolInfo    *disk = Parent->ImplPtr;\r
+       \r
+       ENTER("pParent pFT", Parent, Entry);\r
+       \r
+       // Set Other Data\r
+       node.Inode = Entry->cluster | (Entry->clusterHi<<16) | (Parent->Inode << 32);\r
+       LOG("node.Inode = %llx", node.Inode);\r
+       node.ImplInt = Pos & 0xFFFF;\r
+       node.ImplPtr = disk;\r
+       node.Size = Entry->size;\r
+       LOG("Entry->size = %i", Entry->size);\r
+       node.UID = 0;   node.GID = 0;\r
+       node.NumACLs = 1;\r
+       \r
+       node.Flags = 0;\r
+       if(Entry->attrib & ATTR_DIRECTORY)      node.Flags |= VFS_FFLAG_DIRECTORY;\r
+       if(Entry->attrib & ATTR_READONLY) {\r
+               node.Flags |= VFS_FFLAG_READONLY;\r
+               node.ACLs = &gVFS_ACL_EveryoneRX;       // R-XR-XR-X\r
+       }\r
+       else {\r
+               node.ACLs = &gVFS_ACL_EveryoneRWX;      // RWXRWXRWX\r
+       }\r
+       \r
+       node.ATime = timestamp(0,0,0,\r
+                       ((Entry->adate&0x1F) - 1),      // Days\r
+                       ((Entry->adate&0x1E0) - 1),     // Months\r
+                       1980+((Entry->adate&0xFF00)>>8) // Years\r
+                       );\r
+       \r
+       node.CTime = Entry->ctimems * 10;       // Miliseconds\r
+       node.CTime += timestamp(\r
+                       ((Entry->ctime&0x1F)<<1),       // Seconds\r
+                       ((Entry->ctime&0x3F0)>>5),      // Minutes\r
+                       ((Entry->ctime&0xF800)>>11),    // Hours\r
+                       ((Entry->cdate&0x1F)-1),                // Days\r
+                       ((Entry->cdate&0x1E0)-1),               // Months\r
+                       1980+((Entry->cdate&0xFF00)>>8) // Years\r
+                       );\r
+                       \r
+       node.MTime = timestamp(\r
+                       ((Entry->mtime&0x1F)<<1),       // Seconds\r
+                       ((Entry->mtime&0x3F0)>>5),      // Minutes\r
+                       ((Entry->mtime&0xF800)>>11),    // Hours\r
+                       ((Entry->mdate&0x1F)-1),                // Days\r
+                       ((Entry->mdate&0x1E0)-1),               // Months\r
+                       1980+((Entry->mdate&0xFF00)>>8) // Years\r
+                       );\r
+       \r
+       if(node.Flags & VFS_FFLAG_DIRECTORY) {\r
+               //Log_Debug("FAT", "Directory %08x has size 0x%x", node.Inode, node.Size);\r
+               node.ReadDir = FAT_ReadDir;\r
+               node.FindDir = FAT_FindDir;\r
+               #if SUPPORT_WRITE\r
+               node.MkNod = FAT_Mknod;\r
+               node.Relink = FAT_Relink;\r
+               #endif\r
+               node.Size = -1;\r
+       } else {\r
+               node.Read = FAT_Read;\r
+               #if SUPPORT_WRITE\r
+               node.Write = FAT_Write;\r
+               #endif\r
+       }\r
+       node.Close = FAT_CloseFile;\r
+       \r
+       ret = Inode_CacheNode(disk->inodeHandle, &node);\r
+       LEAVE('p', ret);\r
+       return ret;\r
+}\r
+\r
+/* ====================\r
+ *     Directory IO\r
+ * ====================\r
+ */\r
+\r
+/**\r
+ * \brief Reads a sector from the disk\r
+ */\r
+int FAT_int_ReadDirSector(tVFS_Node *Node, int Sector, fat_filetable *Buffer)\r
+{\r
+       Uint64  addr;\r
+       tFAT_VolInfo    *disk = Node->ImplPtr;\r
+       \r
+       ENTER("pNode iSector pEntry", Node, Sector, Buffer);\r
+       \r
+       if(FAT_int_GetAddress(Node, Sector * 512, &addr, NULL))\r
+       {\r
+               LEAVE('i', 1);\r
+               return 1;\r
+       }\r
+       \r
+       // Read Sector\r
+       if(VFS_ReadAt(disk->fileHandle, addr, 512, Buffer) != 512)\r
+       {\r
+               LEAVE('i', 1);\r
+               return 1;\r
+       }\r
+       \r
+       LEAVE('i', 0);\r
+       return 0;\r
+}\r
+\r
+#if SUPPORT_WRITE\r
+/**\r
+ * \brief Writes an entry to the disk\r
+ * \todo Support expanding a directory\r
+ * \return Zero on success, non-zero on error\r
+ */\r
+int FAT_int_WriteDirEntry(tVFS_Node *Node, int ID, fat_filetable *Entry)\r
+{\r
+       Uint64  addr = 0;\r
+        int    tmp;\r
+       Uint32  cluster = 0;\r
+       tFAT_VolInfo    *disk = Node->ImplPtr;\r
+       \r
+       ENTER("pNode iID pEntry", Node, ID, Entry);\r
+       \r
+       tmp = FAT_int_GetAddress(Node, ID * sizeof(fat_filetable), &addr, &cluster);\r
+       if( tmp )\r
+       {\r
+               //TODO: Allocate a cluster\r
+               cluster = FAT_int_AllocateCluster(Node->ImplPtr, cluster);\r
+               if(cluster == -1) {\r
+                       Log_Warning("FAT", "Unable to allocate an other cluster for %p", Node);\r
+                       LEAVE('i', 1);\r
+                       return 1;\r
+               }\r
+               FAT_int_GetAddress(Node, ID * sizeof(fat_filetable), &addr, &cluster);\r
+       }\r
+       \r
+\r
+       LOG("addr = 0x%llx", addr);\r
+       \r
+       // Read Sector\r
+       VFS_WriteAt(disk->fileHandle, addr, sizeof(fat_filetable), Entry);      // Read Dir Data\r
+       \r
+       LEAVE('i', 0);\r
+       return 0;\r
+}\r
+#endif\r
+\r
+#if USE_LFN\r
+// I should probably more tightly associate the LFN cache with the node\r
+// somehow, maybe by adding a field to tVFS_Node before locking it\r
+// Maybe .Cache or something like that (something that is free'd by the\r
+// Inode_UncacheNode function)\r
+       \r
+/**\r
+ * \fn char *FAT_int_GetLFN(tVFS_Node *node)\r
+ * \brief Return pointer to LFN cache entry\r
+ */\r
+char *FAT_int_GetLFN(tVFS_Node *node)\r
+{\r
+       t_lfncache      *tmp;\r
+       tmp = fat_lfncache;\r
+       while(tmp)\r
+       {\r
+               if(tmp->Inode == node->Inode && tmp->Disk == node->ImplPtr)\r
+                       return tmp->Name;\r
+               tmp = tmp->Next;\r
+       }\r
+       tmp = malloc(sizeof(t_lfncache));\r
+       tmp->Inode = node->Inode;\r
+       tmp->Disk = node->ImplPtr;\r
+       memset(tmp->Name, 0, 256);\r
+       \r
+       tmp->Next = fat_lfncache;\r
+       fat_lfncache = tmp;\r
+       \r
+       return tmp->Name;\r
+}\r
+\r
+/**\r
+ * \fn void FAT_int_DelLFN(tVFS_Node *node)\r
+ * \brief Delete a LFN cache entry\r
+ */\r
+void FAT_int_DelLFN(tVFS_Node *node)\r
+{\r
+       t_lfncache      *tmp;\r
+       \r
+       if(!fat_lfncache)       return;\r
+       \r
+       if(!fat_lfncache->Next)\r
+       {\r
+               tmp = fat_lfncache;\r
+               fat_lfncache = tmp->Next;\r
+               free(tmp);\r
+               return;\r
+       }\r
+       tmp = fat_lfncache;\r
+       while(tmp && tmp->Next)\r
+       {\r
+               if(tmp->Inode == node->Inode && tmp->Disk == node->ImplPtr)\r
+               {\r
+                       free(tmp->Next);\r
+                       tmp->Next = tmp->Next->Next;\r
+                       return;\r
+               }\r
+               tmp = tmp->Next;\r
+       }\r
+}\r
+#endif\r
+\r
+/**\r
+ * \fn char *FAT_ReadDir(tVFS_Node *Node, int ID)\r
+ * \param Node Node structure of directory\r
+ * \param ID   Directory position\r
+ */\r
+char *FAT_ReadDir(tVFS_Node *Node, int ID)\r
+{\r
+       fat_filetable   fileinfo[16];   //Sizeof=32, 16 per sector\r
+        int    a=0;\r
+       char    *ret;\r
+       #if USE_LFN\r
+       char    *lfn = NULL;\r
+       #endif\r
+       \r
+       ENTER("pNode iID", Node, ID);\r
+       \r
+       if(FAT_int_ReadDirSector(Node, ID/16, fileinfo))\r
+       {\r
+               LEAVE('n');\r
+               return NULL;\r
+       }\r
+       \r
+       // Offset in sector\r
+       a = ID % 16;\r
+\r
+       LOG("a = %i", a);\r
+       \r
+       LOG("name[0] = 0x%x", (Uint8)fileinfo[a].name[0]);\r
+       \r
+       // Check if this is the last entry\r
+       if( fileinfo[a].name[0] == '\0' ) {\r
+               Node->Size = ID;\r
+               LOG("End of list");\r
+               LEAVE('n');\r
+               return NULL;    // break\r
+       }\r
+       \r
+       // Check for empty entry\r
+       if( (Uint8)fileinfo[a].name[0] == 0xE5 ) {\r
+               LOG("Empty Entry");\r
+               LEAVE('p', VFS_SKIP);\r
+               return VFS_SKIP;        // Skip\r
+       }\r
+       \r
+       #if USE_LFN\r
+       // Get Long File Name Cache\r
+       lfn = FAT_int_GetLFN(Node);\r
+       if(fileinfo[a].attrib == ATTR_LFN)\r
+       {\r
+               fat_longfilename        *lfnInfo;\r
+                int    len;\r
+               \r
+               lfnInfo = (fat_longfilename *) &fileinfo[a];\r
+               if(lfnInfo->id & 0x40)  memset(lfn, 0, 256);\r
+               // Get the current length\r
+               len = strlen(lfn);\r
+               \r
+               // Sanity Check (FAT implementations should not allow >255 bytes)\r
+               if(len + 13 > 255)      return VFS_SKIP;\r
+               // Rebase all bytes\r
+               for(a=len+1;a--;)       lfn[a+13] = lfn[a];\r
+               \r
+               // Append new bytes\r
+               lfn[ 0] = lfnInfo->name1[0];    lfn[ 1] = lfnInfo->name1[1];\r
+               lfn[ 2] = lfnInfo->name1[2];    lfn[ 3] = lfnInfo->name1[3];\r
+               lfn[ 4] = lfnInfo->name1[4];    \r
+               lfn[ 5] = lfnInfo->name2[0];    lfn[ 6] = lfnInfo->name2[1];\r
+               lfn[ 7] = lfnInfo->name2[2];    lfn[ 8] = lfnInfo->name2[3];\r
+               lfn[ 9] = lfnInfo->name2[4];    lfn[10] = lfnInfo->name2[5];\r
+               lfn[11] = lfnInfo->name3[0];    lfn[12] = lfnInfo->name3[1];\r
+               LOG("lfn = '%s'", lfn);\r
+               LEAVE('p', VFS_SKIP);\r
+               return VFS_SKIP;\r
+       }\r
+       #endif\r
+       \r
+       //Check if it is a volume entry\r
+       if(fileinfo[a].attrib & 0x08) {\r
+               LEAVE('p', VFS_SKIP);\r
+               return VFS_SKIP;\r
+       }\r
+       // Ignore . and ..\r
+       if(fileinfo[a].name[0] == '.') {\r
+               LEAVE('p', VFS_SKIP);\r
+               return VFS_SKIP;\r
+       }       \r
+       \r
+       LOG("name='%c%c%c%c%c%c%c%c.%c%c%c'",\r
+               fileinfo[a].name[0], fileinfo[a].name[1], fileinfo[a].name[2], fileinfo[a].name[3],\r
+               fileinfo[a].name[4], fileinfo[a].name[5], fileinfo[a].name[6], fileinfo[a].name[7],\r
+               fileinfo[a].name[8], fileinfo[a].name[9], fileinfo[a].name[10] );\r
+       \r
+       #if USE_LFN\r
+       ret = FAT_int_CreateName(&fileinfo[a], lfn);\r
+       lfn[0] = '\0';\r
+       #else\r
+       ret = FAT_int_CreateName(&fileinfo[a], NULL);\r
+       #endif\r
+       \r
+       LEAVE('s', ret);\r
+       return ret;\r
+}\r
+\r
+/**\r
+ * \fn tVFS_Node *FAT_FindDir(tVFS_Node *node, char *name)\r
+ * \brief Finds an entry in the current directory\r
+ */\r
+tVFS_Node *FAT_FindDir(tVFS_Node *Node, char *Name)\r
+{\r
+       fat_filetable   fileinfo[16];\r
+       char    tmpName[13];\r
+       #if USE_LFN\r
+       fat_longfilename        *lfnInfo;\r
+       char    lfn[256];\r
+        int    lfnPos=255, lfnId = -1;\r
+       #endif\r
+        int    i;\r
+       tVFS_Node       *tmpNode;\r
+       tFAT_VolInfo    *disk = Node->ImplPtr;\r
+       Uint32  cluster;\r
+       \r
+       ENTER("pNode sname", Node, Name);\r
+       \r
+       // Fast Returns\r
+       if(!Name || Name[0] == '\0') {\r
+               LEAVE('n');\r
+               return NULL;\r
+       }\r
+       \r
+       for( i = 0; ; i++ )\r
+       {\r
+               if((i & 0xF) == 0) {\r
+                       if(FAT_int_ReadDirSector(Node, i/16, fileinfo))\r
+                       {\r
+                               LEAVE('n');\r
+                               return NULL;\r
+                       }\r
+               }\r
+               \r
+               //Check if the files are free\r
+               if(fileinfo[i&0xF].name[0] == '\0')     break;  // End of List marker\r
+               if(fileinfo[i&0xF].name[0] == '\xE5')   continue;       // Free entry\r
+               \r
+               \r
+               #if USE_LFN\r
+               // Long File Name Entry\r
+               if(fileinfo[i&0xF].attrib == ATTR_LFN)\r
+               {\r
+                       lfnInfo = (fat_longfilename *) &fileinfo[i&0xF];\r
+                       if(lfnInfo->id & 0x40) {\r
+                               memset(lfn, 0, 256);\r
+                               lfnPos = 255;\r
+                       }\r
+                       lfn[lfnPos--] = lfnInfo->name3[1];      lfn[lfnPos--] = lfnInfo->name3[0];\r
+                       lfn[lfnPos--] = lfnInfo->name2[5];      lfn[lfnPos--] = lfnInfo->name2[4];\r
+                       lfn[lfnPos--] = lfnInfo->name2[3];      lfn[lfnPos--] = lfnInfo->name2[2];\r
+                       lfn[lfnPos--] = lfnInfo->name2[1];      lfn[lfnPos--] = lfnInfo->name2[0];\r
+                       lfn[lfnPos--] = lfnInfo->name1[4];      lfn[lfnPos--] = lfnInfo->name1[3];\r
+                       lfn[lfnPos--] = lfnInfo->name1[2];      lfn[lfnPos--] = lfnInfo->name1[1];\r
+                       lfn[lfnPos--] = lfnInfo->name1[0];\r
+                       if((lfnInfo->id&0x3F) == 1)\r
+                       {\r
+                               memcpy(lfn, lfn+lfnPos+1, 256-lfnPos);\r
+                               lfnId = i+1;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       // Remove LFN if it does not apply\r
+                       if(lfnId != i)  lfn[0] = '\0';\r
+               #endif\r
+                       // Get Real Filename\r
+                       FAT_int_ProperFilename(tmpName, fileinfo[i&0xF].name);\r
+                       LOG("tmpName = '%s'", tmpName);\r
+               \r
+                       // Only the long name is case sensitive, 8.3 is not\r
+                       #if USE_LFN\r
+                       if(strucmp(tmpName, Name) == 0 || strcmp(lfn, Name) == 0)\r
+                       #else\r
+                       if(strucmp(tmpName, Name) == 0)\r
+                       #endif\r
+                       {\r
+                               cluster = fileinfo[i&0xF].cluster | (fileinfo[i&0xF].clusterHi << 16);\r
+                               tmpNode = Inode_GetCache(disk->inodeHandle, cluster);\r
+                               if(tmpNode == NULL)     // Node is not cached\r
+                               {\r
+                                       tmpNode = FAT_int_CreateNode(Node, &fileinfo[i&0xF], i);\r
+                               }\r
+                               LEAVE('p', tmpNode);\r
+                               return tmpNode;\r
+                       }\r
+               #if USE_LFN\r
+               }\r
+               #endif\r
+       }\r
+       \r
+       LEAVE('n');\r
+       return NULL;\r
+}\r
+\r
+#if SUPPORT_WRITE\r
+/**\r
+ * \fn int FAT_Mknod(tVFS_Node *Node, char *Name, Uint Flags)\r
+ * \brief Create a new node\r
+ */\r
+int FAT_Mknod(tVFS_Node *Node, char *Name, Uint Flags)\r
+{\r
+       return 0;\r
+}\r
+\r
+/**\r
+ * \fn int FAT_Relink(tVFS_Node *Node, char *OldName, char *NewName)\r
+ * \brief Rename / Delete a file\r
+ */\r
+int FAT_Relink(tVFS_Node *Node, char *OldName, char *NewName)\r
+{\r
+       tVFS_Node       *child;\r
+       fat_filetable   ft = {0};\r
+        int    ret;\r
+       \r
+       child = FAT_FindDir(Node, OldName);\r
+       if(!child)      return ENOTFOUND;\r
+       \r
+       // Delete?\r
+       if( NewName == NULL )\r
+       {\r
+               child->ImplInt |= FAT_FLAG_DELETE;      // Mark for deletion on close\r
+               \r
+               // Delete from the directory\r
+               ft.name[0] = '\xE9';\r
+               FAT_int_WriteDirEntry(Node, child->ImplInt & 0xFFFF, &ft);\r
+               \r
+               // Return success\r
+               ret = EOK;\r
+       }\r
+       // Rename\r
+       else\r
+       {\r
+               Log_Warning("FAT", "Renaming no yet supported %p ('%s' => '%s')",\r
+                       Node, OldName, NewName);\r
+               ret = ENOTIMPL;\r
+       }\r
+       \r
+       // Close child\r
+       child->Close( child );\r
+       return ret;\r
+}\r
+#endif\r
+\r
+/**\r
+ * \fn void FAT_CloseFile(tVFS_Node *Node)\r
+ * \brief Close an open file\r
+ */\r
+void FAT_CloseFile(tVFS_Node *Node)\r
+{\r
+       tFAT_VolInfo    *disk = Node->ImplPtr;\r
+       if(Node == NULL)        return ;\r
+       \r
+       #if SUPPORT_WRITE\r
+       // Update the node if it's dirty (don't bother if it's marked for\r
+       // deletion)\r
+       if( Node->ImplInt & FAT_FLAG_DIRTY && !(Node->ImplInt & FAT_FLAG_DELETE) )\r
+       {\r
+               tFAT_VolInfo    buf[16];\r
+               tFAT_VolInfo    *ft = &buf[ (Node->ImplInt & 0xFFFF) % 16 ];\r
+               \r
+               FAT_int_ReadDirSector(Node, (Node->ImplInt & 0xFFFF)/16, buf);\r
+               ft->size = Node->Size;\r
+               // TODO: update adate, mtime, mdate\r
+               FAT_int_WriteDirEntry(Node, Node->ImplInt & 0xFFFF, ft);\r
+               \r
+               Node->ImplInt &= ~FAT_FLAG_DIRTY;\r
+       }\r
+       #endif\r
+       \r
+       // TODO: Make this more thread safe somehow, probably by moving the\r
+       // Inode_UncacheNode higher up and saving the cluster value somewhere\r
+       if( Node->ReferenceCount == 1 )\r
+       {\r
+               // Delete LFN Cache\r
+               #if USE_LFN\r
+               if(     Node->Flags & VFS_FFLAG_DIRECTORY)\r
+                       FAT_int_DelLFN(Node);\r
+               #endif\r
+               \r
+               #if SUPPORT_WRITE\r
+               // Delete File\r
+               if( Node->ImplInt & FAT_FLAG_DELETE ) {\r
+                       // Since the node is marked, we only need to remove it's data\r
+                       Uint32  cluster = Node->Inode & 0xFFFFFFFF;\r
+                       while( cluster != -1 )\r
+                               cluster = FAT_int_FreeCluster(Node->ImplPtr, cluster);\r
+               }\r
+               #endif\r
+       }\r
+       \r
+       Inode_UncacheNode(disk->inodeHandle, Node->Inode);\r
+       return ;\r
+}\r
diff --git a/Modules/Filesystems/FAT/fs_fat.h b/Modules/Filesystems/FAT/fs_fat.h
new file mode 100644 (file)
index 0000000..072e2bf
--- /dev/null
@@ -0,0 +1,169 @@
+/*\r
+ * Acess2\r
+ * FAT12/16/32 Driver\r
+ * vfs/fs/fs_fat.h\r
+ */\r
+#ifndef _FS_FAT_H_\r
+#define _FS_FAT_H_\r
+\r
+// === On Disk Structures ===\r
+/**\r
+ * \struct fat_bootsect_s\r
+ * \brief Bootsector format\r
+ */\r
+struct fat_bootsect_s\r
+{\r
+       Uint8   jmp[3]; //!< Jump Instruction\r
+       char    oemname[8];     //!< OEM Name. Typically MSDOS1.1\r
+       Uint16  bps;    //!< Bytes per Sector. Assumed to be 512\r
+       Uint8   spc;            //!< Sectors per Cluster\r
+       Uint16  resvSectCount;  //!< Number of reserved sectors at beginning of volume\r
+       Uint8   fatCount;       //!< Number of copies of the FAT\r
+       Uint16  files_in_root;  //!< Count of files in the root directory\r
+       Uint16  totalSect16;    //!< Total sector count (FAT12/16)\r
+       Uint8   mediaDesc;      //!< Media Desctiptor\r
+       Uint16  fatSz16;        //!< FAT Size (FAT12/16)\r
+       Uint16  spt;    //!< Sectors per track. Ignored (Acess uses LBA)\r
+       Uint16  heads;  //!< Heads. Ignored (Acess uses LBA)\r
+       Uint32  hiddenCount;    //!< ???\r
+       Uint32  totalSect32;    //!< Total sector count (FAT32)\r
+       union {\r
+               struct {\r
+                       Uint8   drvNum; //!< Drive Number. BIOS Drive ID (E.g. 0x80)\r
+                       Uint8   resv;   //!< Reserved byte\r
+                       Uint8   bootSig;        //!< Boot Signature. ???\r
+                       Uint32  volId;  //!< Volume ID\r
+                       char    label[11];      //!< Disk Label\r
+                       char    fsType[8];      //!< FS Type. ???\r
+               } __attribute__((packed)) fat16;        //!< FAT16 Specific information\r
+               struct {\r
+                       Uint32  fatSz32;        //!< 32-Bit FAT Size\r
+                       Uint16  extFlags;       //!< Extended flags\r
+                       Uint16  fsVer;  //!< Filesystem Version\r
+                       Uint32  rootClust;      //!< Root Cluster ID\r
+                       Uint16  fsInfo; //!< FS Info. ???\r
+                       Uint16  backupBS;       //!< Backup Bootsector Sector Offset\r
+                       char    resv[12];       //!< Reserved Data\r
+                       Uint8   drvNum; //!< Drive Number\r
+                       char    resv2;  //!< Reserved Data\r
+                       Uint8   bootSig;        //!< Boot Signature. ???\r
+                       Uint32  volId;  //!< Volume ID\r
+                       char    label[11];      //!< Disk Label\r
+                       char    fsType[8];      //!< Filesystem Type. ???\r
+               } __attribute__((packed)) fat32;        //!< FAT32 Specific Information\r
+       }__attribute__((packed)) spec;  //!< Non Shared Data\r
+       char pad[512-90];       //!< Bootsector Data (Code/Boot Signature 0xAA55)\r
+} __attribute__((packed));\r
+\r
+/**\r
+ \struct fat_filetable_s\r
+ \brief Format of a 8.3 file entry on disk\r
+*/\r
+struct fat_filetable_s {\r
+       char    name[11];       //!< 8.3 Name\r
+       Uint8   attrib; //!< File Attributes.\r
+       Uint8   ntres;  //!< Reserved for NT - Set to 0\r
+       Uint8   ctimems;        //!< 10ths of a second ranging from 0-199 (2 seconds)\r
+       Uint16  ctime;  //!< Creation Time\r
+       Uint16  cdate;  //!< Creation Date\r
+       Uint16  adate;  //!< Accessed Date. No Time feild though\r
+       Uint16  clusterHi;      //!< High Cluster. 0 for FAT12 and FAT16\r
+       Uint16  mtime;  //!< Last Modified Time\r
+       Uint16  mdate;  //!< Last Modified Date\r
+       Uint16  cluster;        //!< Low Word of First cluster\r
+       Uint32  size;   //!< Size of file\r
+} __attribute__((packed));\r
+\r
+/**\r
+ \struct fat_longfilename_s\r
+ \brief Format of a long file name entry on disk\r
+*/\r
+struct fat_longfilename_s {\r
+       Uint8   id;     //!< ID of entry. Bit 6 is set for last entry\r
+       Uint16  name1[5];       //!< 5 characters of name\r
+       Uint8   attrib; //!< Attributes. Must be ATTR_LFN\r
+       Uint8   type;   //!< Type. ???\r
+       Uint8   checksum;       //!< Checksum\r
+       Uint16  name2[6];       //!< 6 characters of name\r
+       Uint16  firstCluster;   //!< Used for non LFN compatability. Set to 0\r
+       Uint16  name3[2];       //!< Last 2 characters of name\r
+} __attribute__((packed));\r
+\r
+/**\r
+ * \name File Attributes\r
+ * \brief Flag values for ::fat_filetable_s.attrib\r
+ * \{\r
+ */\r
+#define ATTR_READONLY  0x01    //!< Read-only file\r
+#define ATTR_HIDDEN            0x02    //!< Hidden File\r
+#define ATTR_SYSTEM            0x04    //!< System File\r
+#define ATTR_VOLUMEID  0x08    //!< Volume ID (Deprecated)\r
+#define ATTR_DIRECTORY 0x10    //!< Directory\r
+/**\r
+ * \brief File needs archiving\r
+ * \note User set flag, no significance to the FS driver\r
+ */\r
+#define ATTR_ARCHIVE   0x20\r
+/**\r
+ * \brief Meta Attribute \r
+ * \r
+ * If ::fat_filetable_s.attrib equals ATTR_LFN the file is a LFN entry\r
+ */\r
+#define        ATTR_LFN                (ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUMEID)\r
+/**\r
+ * \}\r
+ */\r
+\r
+/**\r
+ * \brief Internal IDs for FAT types\r
+ */\r
+enum eFatType\r
+{\r
+       FAT12,  //!< FAT12 Volume\r
+       FAT16,  //!< FAT16 Volume\r
+       FAT32,  //!< FAT32 Volume\r
+};\r
+\r
+/**\r
+ * \name End of Cluster marks\r
+ * \brief FAT values that indicate the end of a cluster chain in\r
+ *        different versions.\r
+ * \{\r
+ */\r
+#define        EOC_FAT12       0x0FFF  //!< FAT-12 Mark\r
+#define        EOC_FAT16       0xFFFF  //!< FAT-16 Mark\r
+#define        EOC_FAT32       0x00FFFFFF      //!< FAT-32 Mark\r
+/**\r
+ * \}\r
+ */\r
+\r
+typedef struct fat_bootsect_s fat_bootsect;\r
+typedef struct fat_filetable_s fat_filetable;\r
+typedef struct fat_longfilename_s fat_longfilename;\r
+\r
+// === Memory Structures ===\r
+/**\r
+ * \struct drv_fat_volinfo_s\r
+ * \brief Representation of a volume in memory\r
+ */\r
+struct drv_fat_volinfo_s\r
+{\r
+        int    fileHandle;     //!< File Handle\r
+        int    type;   //!< FAT Type. See eFatType\r
+       char    name[12];       //!< Volume Name (With NULL Terminator)\r
+       tSpinlock       lFAT;   //!< Lock to prevent double-writing to the FAT\r
+       Uint32  firstDataSect;  //!< First data sector\r
+       Uint32  rootOffset;     //!< Root Offset (clusters)\r
+       Uint32  ClusterCount;   //!< Total Cluster Count\r
+       fat_bootsect    bootsect;       //!< Boot Sector\r
+       tVFS_Node       rootNode;       //!< Root Node\r
+        int    BytesPerCluster;\r
+        int    inodeHandle;    //!< Inode Cache Handle\r
+       #if CACHE_FAT\r
+       Uint32  *FATCache;      //!< FAT Cache\r
+       #endif\r
+};\r
+\r
+typedef struct drv_fat_volinfo_s tFAT_VolInfo;\r
+\r
+#endif\r
diff --git a/Modules/Filesystems/FS_Ext2/Makefile b/Modules/Filesystems/FS_Ext2/Makefile
deleted file mode 100644 (file)
index 806e638..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#
-#
-
-OBJ = ext2.o read.o dir.o write.o
-NAME = FS_Ext2
-
--include ../Makefile.tpl
diff --git a/Modules/Filesystems/FS_Ext2/dir.c b/Modules/Filesystems/FS_Ext2/dir.c
deleted file mode 100644 (file)
index 5fe8933..0000000
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * Acess OS
- * Ext2 Driver Version 1
- */
-/**
- * \file dir.c
- * \brief Second Extended Filesystem Driver
- * \todo Implement file full write support
- */
-#define DEBUG  1
-#define VERBOSE        0
-#include "ext2_common.h"
-
-
-// === PROTOTYPES ===
-char           *Ext2_ReadDir(tVFS_Node *Node, int Pos);
-tVFS_Node      *Ext2_FindDir(tVFS_Node *Node, char *FileName);
- int           Ext2_MkNod(tVFS_Node *Node, char *Name, Uint Flags);
-tVFS_Node      *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeId, char *Name);
-
-// === CODE ===
-/**
- \fn char *Ext2_ReadDir(tVFS_Node *Node, int Pos)
- \brief Reads a directory entry
-*/
-char *Ext2_ReadDir(tVFS_Node *Node, int Pos)
-{
-       tExt2_Inode     inode;
-       char    namebuf[EXT2_NAME_LEN+1];
-       tExt2_DirEnt    dirent;
-       Uint64  Base;   // Block's Base Address
-        int    block = 0, ofs = 0;
-        int    entNum = 0;
-       tExt2_Disk      *disk = Node->ImplPtr;
-       Uint    size;
-       
-       ENTER("pNode iPos", Node, Pos);
-       
-       // Read directory's inode
-       Ext2_int_GetInode(Node, &inode);
-       size = inode.i_size;
-       
-       LOG("inode.i_block[0] = 0x%x", inode.i_block[0]);
-       
-       // Find Entry
-       // Get First Block
-       // - Do this ourselves as it is a simple operation
-       Base = inode.i_block[0] * disk->BlockSize;
-       while(Pos -- && size > 0)
-       {
-               VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent);
-               ofs += dirent.rec_len;
-               size -= dirent.rec_len;
-               entNum ++;
-               
-               if(ofs >= disk->BlockSize) {
-                       block ++;
-                       if( ofs > disk->BlockSize ) {
-                               Warning("[EXT2] Directory Entry %i of inode %i extends over a block boundary, ignoring",
-                                       entNum-1, Node->Inode);
-                       }
-                       ofs = 0;
-                       Base = Ext2_int_GetBlockAddr( disk, inode.i_block, block );
-               }
-       }
-       
-       // Check for the end of the list
-       if(size <= 0) {
-               LEAVE('n');
-               return NULL;
-       }
-       
-       // Read Entry
-       VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent );
-       //LOG("dirent.inode = %i", dirent.inode);
-       //LOG("dirent.rec_len = %i", dirent.rec_len);
-       //LOG("dirent.name_len = %i", dirent.name_len);
-       VFS_ReadAt( disk->FD, Base+ofs+sizeof(tExt2_DirEnt), dirent.name_len, namebuf );
-       namebuf[ dirent.name_len ] = '\0';      // Cap off string
-       
-       
-       // Ignore . and .. (these are done in the VFS)
-       if( (namebuf[0] == '.' && namebuf[1] == '\0')
-       ||  (namebuf[0] == '.' && namebuf[1] == '.' && namebuf[2]=='\0')) {
-               LEAVE('p', VFS_SKIP);
-               return VFS_SKIP;        // Skip
-       }
-       
-       LEAVE('s', namebuf);
-       // Create new node
-       return strdup(namebuf);
-}
-
-/**
- \fn tVFS_Node *Ext2_FindDir(tVFS_Node *node, char *filename)
- \brief Gets information about a file
- \param node   vfs node - Parent Node
- \param filename       String - Name of file
- \return VFS Node of file
-*/
-tVFS_Node *Ext2_FindDir(tVFS_Node *Node, char *Filename)
-{
-       tExt2_Disk      *disk = Node->ImplPtr;
-       tExt2_Inode     inode;
-       char    namebuf[EXT2_NAME_LEN+1];
-       tExt2_DirEnt    dirent;
-       Uint64  Base;   // Block's Base Address
-        int    block = 0, ofs = 0;
-        int    entNum = 0;
-       Uint    size;
-       
-       // Read directory's inode
-       Ext2_int_GetInode(Node, &inode);
-       size = inode.i_size;
-       
-       // Get First Block
-       // - Do this ourselves as it is a simple operation
-       Base = inode.i_block[0] * disk->BlockSize;
-       // Find File
-       while(size > 0)
-       {
-               VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent);
-               VFS_ReadAt( disk->FD, Base+ofs+sizeof(tExt2_DirEnt), dirent.name_len, namebuf );
-               namebuf[ dirent.name_len ] = '\0';      // Cap off string
-               // If it matches, create a node and return it
-               if(strcmp(namebuf, Filename) == 0)
-                       return Ext2_int_CreateNode( disk, dirent.inode, namebuf );
-               // Increment pointers
-               ofs += dirent.rec_len;
-               size -= dirent.rec_len;
-               entNum ++;
-               
-               // Check for end of block
-               if(ofs >= disk->BlockSize) {
-                       block ++;
-                       if( ofs > disk->BlockSize ) {
-                               Warning("[EXT2 ] Directory Entry %i of inode %i extends over a block boundary, ignoring",
-                                       entNum-1, Node->Inode);
-                       }
-                       ofs = 0;
-                       Base = Ext2_int_GetBlockAddr( disk, inode.i_block, block );
-               }
-       }
-       
-       return NULL;
-}
-
-/**
- * \fn int Ext2_MkNod(tVFS_Node *Parent, char *Name, Uint Flags)
- * \brief Create a new node
- */
-int Ext2_MkNod(tVFS_Node *Parent, char *Name, Uint Flags)
-{
-       return 0;
-}
-
-// ---- INTERNAL FUNCTIONS ----
-/**
- * \fn vfs_node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeID, char *Name)
- * \brief Create a new VFS Node
- */
-tVFS_Node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeID, char *Name)
-{
-       tExt2_Inode     inode;
-       tVFS_Node       retNode;
-       tVFS_Node       *tmpNode;
-       
-       if( !Ext2_int_ReadInode(Disk, InodeID, &inode) )
-               return NULL;
-       
-       if( (tmpNode = Inode_GetCache(Disk->CacheID, InodeID)) )
-               return tmpNode;
-       
-       
-       // Set identifiers
-       retNode.Inode = InodeID;
-       retNode.ImplPtr = Disk;
-       
-       // Set file length
-       retNode.Size = inode.i_size;
-       
-       // Set Access Permissions
-       retNode.UID = inode.i_uid;
-       retNode.GID = inode.i_gid;
-       retNode.NumACLs = 3;
-       retNode.ACLs = VFS_UnixToAcessACL(inode.i_mode & 0777, inode.i_uid, inode.i_gid);
-       
-       //  Set Function Pointers
-       retNode.Read = Ext2_Read;
-       retNode.Write = Ext2_Write;
-       retNode.Close = Ext2_CloseFile;
-       
-       switch(inode.i_mode & EXT2_S_IFMT)
-       {
-       // Symbolic Link
-       case EXT2_S_IFLNK:
-               retNode.Flags = VFS_FFLAG_SYMLINK;
-               break;
-       // Regular File
-       case EXT2_S_IFREG:
-               retNode.Flags = 0;
-               retNode.Size |= (Uint64)inode.i_dir_acl << 32;
-               break;
-       // Directory
-       case EXT2_S_IFDIR:
-               retNode.ReadDir = Ext2_ReadDir;
-               retNode.FindDir = Ext2_FindDir;
-               retNode.MkNod = Ext2_MkNod;
-               //retNode.Relink = Ext2_Relink;
-               retNode.Flags = VFS_FFLAG_DIRECTORY;
-               break;
-       // Unknown, Write protect and hide it to be safe 
-       default:
-               retNode.Flags = VFS_FFLAG_READONLY;//|VFS_FFLAG_HIDDEN;
-               break;
-       }
-       
-       // Check if the file should be hidden
-       //if(Name[0] == '.')    retNode.Flags |= VFS_FFLAG_HIDDEN;
-       
-       // Set Timestamps
-       retNode.ATime = now();
-       retNode.MTime = inode.i_mtime * 1000;
-       retNode.CTime = inode.i_ctime * 1000;
-       
-       // Save in node cache and return saved node
-       return Inode_CacheNode(Disk->CacheID, &retNode);
-}
diff --git a/Modules/Filesystems/FS_Ext2/ext2.c b/Modules/Filesystems/FS_Ext2/ext2.c
deleted file mode 100644 (file)
index 81dcef0..0000000
+++ /dev/null
@@ -1,309 +0,0 @@
-/*\r
- * Acess OS\r
- * Ext2 Driver Version 1\r
- */\r
-/**\r
- * \file fs/ext2.c\r
- * \brief Second Extended Filesystem Driver\r
- * \todo Implement file full write support\r
- */\r
-#define DEBUG  1\r
-#define VERBOSE        0\r
-#include "ext2_common.h"\r
-#include <modules.h>\r
-\r
-// === PROTOTYPES ===\r
- int   Ext2_Install(char **Arguments);\r
-// Interface Functions\r
-tVFS_Node      *Ext2_InitDevice(char *Device, char **Options);\r
-void           Ext2_Unmount(tVFS_Node *Node);\r
-void           Ext2_CloseFile(tVFS_Node *Node);\r
-// Internal Helpers\r
- int           Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode);\r
-Uint64         Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum);\r
-Uint32         Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent);\r
-void           Ext2_int_UpdateSuperblock(tExt2_Disk *Disk);\r
-\r
-// === SEMI-GLOBALS ===\r
-MODULE_DEFINE(0, 0x5B /*v0.90*/, FS_Ext2, Ext2_Install, NULL);\r
-tExt2_Disk     gExt2_disks[6];\r
- int   giExt2_count = 0;\r
-tVFS_Driver    gExt2_FSInfo = {\r
-       "ext2", 0, Ext2_InitDevice, Ext2_Unmount, NULL\r
-       };\r
-\r
-// === CODE ===\r
-\r
-/**\r
- * \fn int Ext2_Install(char **Arguments)\r
- * \brief Install the Ext2 Filesystem Driver\r
- */\r
-int Ext2_Install(char **Arguments)\r
-{\r
-       VFS_AddDriver( &gExt2_FSInfo );\r
-       return 1;\r
-}\r
-\r
-/**\r
- \fn tVFS_Node *Ext2_InitDevice(char *Device, char **Options)\r
- \brief Initializes a device to be read by by the driver\r
- \param Device String - Device to read from\r
- \param Options        NULL Terminated array of option strings\r
- \return Root Node\r
-*/\r
-tVFS_Node *Ext2_InitDevice(char *Device, char **Options)\r
-{\r
-       tExt2_Disk      *disk;\r
-        int    fd;\r
-        int    groupCount;\r
-       tExt2_SuperBlock        sb;\r
-       tExt2_Inode     inode;\r
-       \r
-       ENTER("sDevice pOptions", Device, Options);\r
-       \r
-       // Open Disk\r
-       fd = VFS_Open(Device, VFS_OPENFLAG_READ|VFS_OPENFLAG_WRITE);            //Open Device\r
-       if(fd == -1) {\r
-               Warning("[EXT2 ] Unable to open '%s'", Device);\r
-               LEAVE('n');\r
-               return NULL;\r
-       }\r
-       \r
-       // Read Superblock at offset 1024\r
-       VFS_ReadAt(fd, 1024, 1024, &sb);        // Read Superblock\r
-       \r
-       // Sanity Check Magic value\r
-       if(sb.s_magic != 0xEF53) {\r
-               Warning("[EXT2 ] Volume '%s' is not an EXT2 volume", Device);\r
-               VFS_Close(fd);\r
-               LEAVE('n');\r
-               return NULL;\r
-       }\r
-       \r
-       // Get Group count\r
-       groupCount = DivUp(sb.s_blocks_count, sb.s_blocks_per_group);\r
-       LOG("groupCount = %i", groupCount);\r
-       \r
-       // Allocate Disk Information\r
-       disk = malloc(sizeof(tExt2_Disk) + sizeof(tExt2_Group)*groupCount);\r
-       if(!disk) {\r
-               Warning("[EXT2 ] Unable to allocate disk structure");\r
-               VFS_Close(fd);\r
-               LEAVE('n');\r
-               return NULL;\r
-       }\r
-       disk->FD = fd;\r
-       memcpy(&disk->SuperBlock, &sb, 1024);\r
-       disk->GroupCount = groupCount;\r
-       \r
-       // Get an inode cache handle\r
-       disk->CacheID = Inode_GetHandle();\r
-       \r
-       // Get Block Size\r
-       LOG("s_log_block_size = 0x%x", sb.s_log_block_size);\r
-       disk->BlockSize = 1024 << sb.s_log_block_size;\r
-       \r
-       // Read Group Information\r
-       VFS_ReadAt(\r
-               disk->FD,\r
-               sb.s_first_data_block * disk->BlockSize + 1024,\r
-               sizeof(tExt2_Group)*groupCount,\r
-               disk->Groups\r
-               );\r
-       \r
-       #if VERBOSE\r
-       LOG("Block Group 0");\r
-       LOG(".bg_block_bitmap = 0x%x", disk->Groups[0].bg_block_bitmap);\r
-       LOG(".bg_inode_bitmap = 0x%x", disk->Groups[0].bg_inode_bitmap);\r
-       LOG(".bg_inode_table = 0x%x", disk->Groups[0].bg_inode_table);\r
-       LOG("Block Group 1");\r
-       LOG(".bg_block_bitmap = 0x%x", disk->Groups[1].bg_block_bitmap);\r
-       LOG(".bg_inode_bitmap = 0x%x", disk->Groups[1].bg_inode_bitmap);\r
-       LOG(".bg_inode_table = 0x%x", disk->Groups[1].bg_inode_table);\r
-       #endif\r
-       \r
-       // Get root Inode\r
-       Ext2_int_ReadInode(disk, 2, &inode);\r
-       \r
-       // Create Root Node\r
-       memset(&disk->RootNode, 0, sizeof(tVFS_Node));\r
-       disk->RootNode.Inode = 2;       // Root inode ID\r
-       disk->RootNode.ImplPtr = disk;  // Save disk pointer\r
-       disk->RootNode.Size = -1;       // Fill in later (on readdir)\r
-       disk->RootNode.Flags = VFS_FFLAG_DIRECTORY;\r
-       \r
-       disk->RootNode.ReadDir = Ext2_ReadDir;\r
-       disk->RootNode.FindDir = Ext2_FindDir;\r
-       //disk->RootNode.Relink = Ext2_Relink;\r
-       \r
-       // Complete root node\r
-       disk->RootNode.UID = inode.i_uid;\r
-       disk->RootNode.GID = inode.i_gid;\r
-       disk->RootNode.NumACLs = 1;\r
-       disk->RootNode.ACLs = &gVFS_ACL_EveryoneRW;\r
-       \r
-       #if DEBUG\r
-       LOG("inode.i_size = 0x%x", inode.i_size);\r
-       LOG("inode.i_block[0] = 0x%x", inode.i_block[0]);\r
-       #endif\r
-       \r
-       LEAVE('p', &disk->RootNode);\r
-       return &disk->RootNode;\r
-}\r
-\r
-/**\r
- * \fn void Ext2_Unmount(tVFS_Node *Node)\r
- * \brief Close a mounted device\r
- */\r
-void Ext2_Unmount(tVFS_Node *Node)\r
-{\r
-       tExt2_Disk      *disk = Node->ImplPtr;\r
-       \r
-       VFS_Close( disk->FD );\r
-       Inode_ClearCache( disk->CacheID );\r
-       memset(disk, 0, sizeof(tExt2_Disk)+disk->GroupCount*sizeof(tExt2_Group));\r
-       free(disk);\r
-}\r
-\r
-/**\r
- * \fn void Ext2_CloseFile(tVFS_Node *Node)\r
- * \brief Close a file (Remove it from the cache)\r
- */\r
-void Ext2_CloseFile(tVFS_Node *Node)\r
-{\r
-       tExt2_Disk      *disk = Node->ImplPtr;\r
-       Inode_UncacheNode(disk->CacheID, Node->Inode);\r
-       return ;\r
-}\r
-\r
-//==================================\r
-//=       INTERNAL FUNCTIONS       =\r
-//==================================\r
-\r
-\r
-/**\r
- * \fn int Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode)\r
- * \brief Gets the inode descriptor for a node\r
- * \param Node node to get the Inode of\r
- * \param Inode        Destination\r
- */\r
-int Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode)\r
-{\r
-       return Ext2_int_ReadInode(Node->ImplPtr, Node->Inode, Inode);\r
-}\r
-\r
-/**\r
- * \fn int Ext2_int_ReadInode(tExt2_Disk *Disk, Uint InodeId, tExt2_Inode *Inode)\r
- * \brief Read an inode into memory\r
- */\r
-int Ext2_int_ReadInode(tExt2_Disk *Disk, Uint InodeId, tExt2_Inode *Inode)\r
-{\r
-        int    group, subId;\r
-       \r
-       //LogF("Ext2_int_ReadInode: (Disk=%p, InodeId=%i, Inode=%p)", Disk, InodeId, Inode);\r
-       //ENTER("pDisk iInodeId pInode", Disk, InodeId, Inode);\r
-       \r
-       if(InodeId == 0)        return 0;\r
-       \r
-       InodeId --;     // Inodes are numbered starting at 1\r
-       \r
-       group = InodeId / Disk->SuperBlock.s_inodes_per_group;\r
-       subId = InodeId % Disk->SuperBlock.s_inodes_per_group;\r
-       \r
-       //LOG("group=%i, subId = %i", group, subId);\r
-       \r
-       // Read Inode\r
-       VFS_ReadAt(Disk->FD,\r
-               Disk->Groups[group].bg_inode_table * Disk->BlockSize + sizeof(tExt2_Inode)*subId,\r
-               sizeof(tExt2_Inode),\r
-               Inode);\r
-       return 1;\r
-}\r
-\r
-/**\r
- * \fn Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum)\r
- * \brief Get the address of a block from an inode's list\r
- * \param Disk Disk information structure\r
- * \param Blocks       Pointer to an inode's block list\r
- * \param BlockNum     Block index in list\r
- */\r
-Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum)\r
-{\r
-       Uint32  *iBlocks;\r
-       // Direct Blocks\r
-       if(BlockNum < 12)\r
-               return (Uint64)Blocks[BlockNum] * Disk->BlockSize;\r
-       \r
-       // Single Indirect Blocks\r
-       iBlocks = malloc( Disk->BlockSize );\r
-       VFS_ReadAt(Disk->FD, (Uint64)Blocks[12]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
-       \r
-       BlockNum -= 12;\r
-       if(BlockNum < 256) {\r
-               BlockNum = iBlocks[BlockNum];\r
-               free(iBlocks);\r
-               return (Uint64)BlockNum * Disk->BlockSize;\r
-       }\r
-       \r
-       // Double Indirect Blocks\r
-       if(BlockNum < 256*256)\r
-       {\r
-               VFS_ReadAt(Disk->FD, (Uint64)Blocks[13]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
-               VFS_ReadAt(Disk->FD, (Uint64)iBlocks[BlockNum/256]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
-               BlockNum = iBlocks[BlockNum%256];\r
-               free(iBlocks);\r
-               return (Uint64)BlockNum * Disk->BlockSize;\r
-       }\r
-       // Triple Indirect Blocks\r
-       VFS_ReadAt(Disk->FD, (Uint64)Blocks[14]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
-       VFS_ReadAt(Disk->FD, (Uint64)iBlocks[BlockNum/(256*256)]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
-       VFS_ReadAt(Disk->FD, (Uint64)iBlocks[(BlockNum/256)%256]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
-       BlockNum = iBlocks[BlockNum%256];\r
-       free(iBlocks);\r
-       return (Uint64)BlockNum * Disk->BlockSize;\r
-}\r
-\r
-/**\r
- * \fn Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent)\r
- * \brief Allocate an inode (from the current group preferably)\r
- * \param Disk EXT2 Disk Information Structure\r
- * \param Parent       Inode ID of the parent (used to locate the child nearby)\r
- */\r
-Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent)\r
-{\r
-//     Uint    block = (Parent - 1) / Disk->SuperBlock.s_inodes_per_group;\r
-       return 0;\r
-}\r
-\r
-/**\r
- * \fn void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk)\r
- * \brief Updates the superblock\r
- */\r
-void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk)\r
-{\r
-        int    bpg = Disk->SuperBlock.s_blocks_per_group;\r
-        int    ngrp = Disk->SuperBlock.s_blocks_count / bpg;\r
-        int    i;\r
-        \r
-       // Update Primary\r
-       VFS_WriteAt(Disk->FD, 1024, 1024, &Disk->SuperBlock);\r
-       \r
-       // Secondaries\r
-       // at Block Group 1, 3^n, 5^n, 7^n\r
-       \r
-       // 1\r
-       if(ngrp <= 1)   return;\r
-       VFS_WriteAt(Disk->FD, 1*bpg*Disk->BlockSize, 1024, &Disk->SuperBlock);\r
-       \r
-       // Powers of 3\r
-       for( i = 3; i < ngrp; i *= 3 )\r
-               VFS_WriteAt(Disk->FD, i*bpg*Disk->BlockSize, 1024, &Disk->SuperBlock);\r
-       \r
-       // Powers of 5\r
-       for( i = 5; i < ngrp; i *= 5 )\r
-               VFS_WriteAt(Disk->FD, i*bpg*Disk->BlockSize, 1024, &Disk->SuperBlock);\r
-       \r
-       // Powers of 7\r
-       for( i = 7; i < ngrp; i *= 7 )\r
-               VFS_WriteAt(Disk->FD, i*bpg*Disk->BlockSize, 1024, &Disk->SuperBlock);\r
-}\r
diff --git a/Modules/Filesystems/FS_Ext2/ext2_common.h b/Modules/Filesystems/FS_Ext2/ext2_common.h
deleted file mode 100644 (file)
index 2e2baba..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Acess OS
- * Ext2 Driver Version 1
- */
-/**
- * \file ext2_common.h
- * \brief Second Extended Filesystem Driver
- */
-#ifndef _EXT2_COMMON_H
-#define _EXT2_COMMON_H
-#include <acess.h>
-#include <vfs.h>
-#include "ext2fs.h"
-
-#define EXT2_UPDATE_WRITEBACK  1
-
-// === STRUCTURES ===
-typedef struct {
-        int    FD;
-        int    CacheID;
-       tVFS_Node       RootNode;
-       
-       tExt2_SuperBlock        SuperBlock;
-        int    BlockSize;
-        
-        int    GroupCount;
-       tExt2_Group             Groups[];
-} tExt2_Disk;
-
-// === FUNCTIONS ===
-// --- Common ---
-extern void    Ext2_CloseFile(tVFS_Node *Node);
-extern int     Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode);
-extern Uint64  Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum);
-extern void    Ext2_int_UpdateSuperblock(tExt2_Disk *Disk);
-// --- Dir ---
-extern char    *Ext2_ReadDir(tVFS_Node *Node, int Pos);
-extern tVFS_Node       *Ext2_FindDir(tVFS_Node *Node, char *FileName);
-extern int     Ext2_MkNod(tVFS_Node *Node, char *Name, Uint Flags);
-// --- Read ---
-extern Uint64  Ext2_Read(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer);
-extern int     Ext2_int_ReadInode(tExt2_Disk *Disk, Uint InodeId, tExt2_Inode *Inode);
-// --- Write ---
-extern Uint64  Ext2_Write(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer);
-
-#endif
diff --git a/Modules/Filesystems/FS_Ext2/ext2fs.h b/Modules/Filesystems/FS_Ext2/ext2fs.h
deleted file mode 100644 (file)
index 8fd87ce..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-/**\r
- * Acess2\r
- * \file ext2fs.h\r
- * \brief EXT2 Filesystem Driver\r
- */\r
-#ifndef _EXT2FS_H_\r
-#define _EXT2FS_H_\r
-\r
-/**\r
- \name Inode Flag Values\r
- \{\r
-*/\r
-#define EXT2_S_IFMT            0xF000  //!< Format Mask\r
-#define EXT2_S_IFSOCK  0xC000  //!< Socket\r
-#define EXT2_S_IFLNK   0xA000  //!< Symbolic Link\r
-#define EXT2_S_IFREG   0x8000  //!< Regular File\r
-#define EXT2_S_IFBLK   0x6000  //!< Block Device\r
-#define EXT2_S_IFDIR   0x4000  //!< Directory\r
-#define EXT2_S_IFCHR   0x2000  //!< Character Device\r
-#define EXT2_S_IFIFO   0x1000  //!< FIFO\r
-#define EXT2_S_ISUID   0x0800  //!< SUID\r
-#define EXT2_S_ISGID   0x0400  //!< SGID\r
-#define EXT2_S_ISVTX   0x0200  //!< sticky bit\r
-#define EXT2_S_IRWXU   0700    //!< user access rights mask\r
-#define EXT2_S_IRUSR   0400    //!< Owner Read\r
-#define EXT2_S_IWUSR   0200    //!< Owner Write\r
-#define EXT2_S_IXUSR   0100    //!< Owner Execute\r
-#define EXT2_S_IRWXG   0070    //!< Group Access rights mask\r
-#define EXT2_S_IRGRP   0040    //!< Group Read\r
-#define EXT2_S_IWGRP   0020    //!< Group Write\r
-#define EXT2_S_IXGRP   0010    //!< Group Execute\r
-#define EXT2_S_IRWXO   0007    //!< Global Access rights mask\r
-#define EXT2_S_IROTH   0004    //!< Global Read\r
-#define EXT2_S_IWOTH   0002    //!< Global Write\r
-#define EXT2_S_IXOTH   0001    //!< Global Execute\r
-//! \}\r
-\r
-#define EXT2_NAME_LEN 255      //!< Maximum Name Length\r
-\r
-// === TYPEDEFS ===\r
-typedef struct ext2_inode_s                    tExt2_Inode;    //!< Inode Type\r
-typedef struct ext2_super_block_s      tExt2_SuperBlock;       //!< Superblock Type\r
-typedef struct ext2_group_desc_s       tExt2_Group;    //!< Group Descriptor Type\r
-typedef struct ext2_dir_entry_s                tExt2_DirEnt;   //!< Directory Entry Type\r
-\r
-// === STRUCTURES ===\r
-/**\r
- * \brief EXT2 Superblock Structure\r
- */\r
-struct ext2_super_block_s {\r
-       Uint32  s_inodes_count;         //!< Inodes count\r
-       Uint32  s_blocks_count;         //!< Blocks count\r
-       Uint32  s_r_blocks_count;       //!< Reserved blocks count\r
-       Uint32  s_free_blocks_count;    //!< Free blocks count\r
-       Uint32  s_free_inodes_count;    //!< Free inodes count\r
-       Uint32  s_first_data_block;     //!< First Data Block\r
-       Uint32  s_log_block_size;       //!< Block size\r
-       Sint32  s_log_frag_size;        //!< Fragment size\r
-       Uint32  s_blocks_per_group;     //!< Number Blocks per group\r
-       Uint32  s_frags_per_group;      //!< Number Fragments per group\r
-       Uint32  s_inodes_per_group;     //!< Number Inodes per group\r
-       Uint32  s_mtime;                        //!< Mount time\r
-       Uint32  s_wtime;                        //!< Write time\r
-       Uint16  s_mnt_count;            //!< Mount count\r
-       Sint16  s_max_mnt_count;        //!< Maximal mount count\r
-       Uint16  s_magic;                        //!< Magic signature\r
-       Uint16  s_state;                        //!< File system state\r
-       Uint16  s_errors;                       //!< Behaviour when detecting errors\r
-       Uint16  s_pad;                          //!< Padding\r
-       Uint32  s_lastcheck;            //!< time of last check\r
-       Uint32  s_checkinterval;        //!< max. time between checks\r
-       Uint32  s_creator_os;           //!< Formatting OS\r
-       Uint32  s_rev_level;            //!< Revision level\r
-       Uint16  s_def_resuid;           //!< Default uid for reserved blocks\r
-       Uint16  s_def_resgid;           //!< Default gid for reserved blocks\r
-       Uint32  s_reserved[235];        //!< Padding to the end of the block\r
-};\r
-\r
-/**\r
- * \struct ext2_inode_s\r
- * \brief EXT2 Inode Definition\r
- */\r
-struct ext2_inode_s {\r
-       Uint16 i_mode;  //!< File mode\r
-       Uint16 i_uid;   //!< Owner Uid\r
-       Uint32 i_size;  //!< Size in bytes\r
-       Uint32 i_atime; //!< Access time\r
-       Uint32 i_ctime; //!< Creation time\r
-       Uint32 i_mtime; //!< Modification time\r
-       Uint32 i_dtime; //!< Deletion Time\r
-       Uint16 i_gid;   //!< Group Id\r
-       Uint16 i_links_count;   //!< Links count\r
-       Uint32 i_blocks;        //!< Number of blocks allocated for the file\r
-       Uint32 i_flags; //!< File flags\r
-       union {\r
-               Uint32 linux_reserved1; //!< Linux: Reserved\r
-               Uint32 hurd_translator; //!< HURD: Translator\r
-               Uint32 masix_reserved1; //!< Masix: Reserved\r
-       } osd1; //!< OS dependent 1\r
-       Uint32 i_block[15];     //!< Pointers to blocks\r
-       Uint32 i_version;       //!< File version (for NFS)\r
-       Uint32 i_file_acl;      //!< File ACL\r
-       Uint32 i_dir_acl;       //!< Directory ACL / Extended File Size\r
-       Uint32 i_faddr;         //!< Fragment address\r
-       union {\r
-               struct {\r
-                       Uint8 l_i_frag; //!< Fragment number\r
-                       Uint8 l_i_fsize;        //!< Fragment size\r
-                       Uint16 i_pad1;  //!< Padding\r
-                       Uint32 l_i_reserved2[2];        //!< Reserved\r
-               } linux2;\r
-               struct {\r
-                       Uint8 h_i_frag; //!< Fragment number\r
-                       Uint8 h_i_fsize; //!< Fragment size\r
-                       Uint16 h_i_mode_high;   //!< Mode High Bits\r
-                       Uint16 h_i_uid_high;    //!< UID High Bits\r
-                       Uint16 h_i_gid_high;    //!< GID High Bits\r
-                       Uint32 h_i_author;      //!< Creator ID\r
-               } hurd2;\r
-               struct {\r
-                       Uint8 m_i_frag; //!< Fragment number\r
-                       Uint8 m_i_fsize;        //!< Fragment size\r
-                       Uint16 m_pad1;  //!< Padding\r
-                       Uint32 m_i_reserved2[2];        //!< reserved\r
-               } masix2;\r
-       } osd2; //!< OS dependent 2\r
-};\r
-\r
-/**\r
- * \struct ext2_group_desc_s\r
- * \brief EXT2 Group Descriptor\r
- */\r
-struct ext2_group_desc_s {\r
-       Uint32  bg_block_bitmap;        //!< Blocks bitmap block\r
-       Uint32  bg_inode_bitmap;        //!< Inodes bitmap block\r
-       Uint32  bg_inode_table; //!< Inodes table block\r
-       Uint16  bg_free_blocks_count;   //!< Free blocks count\r
-       Uint16  bg_free_inodes_count;   //!< Free inodes count\r
-       Uint16  bg_used_dirs_count;     //!< Directories count\r
-       Uint16  bg_pad; //!< Padding\r
-       Uint32  bg_reserved[3]; //!< Reserved\r
-};\r
-\r
-/**\r
- * \brief EXT2 Directory Entry\r
- * \note The name may take up less than 255 characters\r
- */\r
-struct ext2_dir_entry_s {\r
-       Uint32  inode;          //!< Inode number\r
-       Uint16  rec_len;        //!< Directory entry length\r
-       Uint8   name_len;       //!< Short Name Length\r
-       Uint8   type;           //!< File Type\r
-       char    name[];         //!< File name\r
-};\r
-\r
-#endif\r
diff --git a/Modules/Filesystems/FS_Ext2/read.c b/Modules/Filesystems/FS_Ext2/read.c
deleted file mode 100644 (file)
index cb6649a..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Acess OS
- * Ext2 Driver Version 1
- */
-/**
- * \file read.c
- * \brief Second Extended Filesystem Driver
- * \todo Implement file full write support
- */
-#define DEBUG  1
-#define VERBOSE        0
-#include "ext2_common.h"
-
-// === PROTOTYPES ===
-Uint64         Ext2_Read(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer);
- int           Ext2_int_ReadInode(tExt2_Disk *Disk, Uint InodeId, tExt2_Inode *Inode);
-
-// === CODE ===
-/**
- * \fn Uint64 Ext2_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
- * \brief Read from a file
- */
-Uint64 Ext2_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
-{
-       tExt2_Disk      *disk = Node->ImplPtr;
-       tExt2_Inode     inode;
-       Uint64  base;
-       Uint    block;
-       Uint64  remLen;
-       
-       ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);
-       
-       // Get Inode
-       Ext2_int_GetInode(Node, &inode);
-       
-       // Sanity Checks
-       if(Offset >= inode.i_size) {
-               LEAVE('i', 0);
-               return 0;
-       }
-       if(Offset + Length > inode.i_size)
-               Length = inode.i_size - Offset;
-       
-       block = Offset / disk->BlockSize;
-       Offset = Offset / disk->BlockSize;
-       base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
-       if(base == 0) {
-               Warning("[EXT2 ] NULL Block Detected in INode 0x%llx", Node->Inode);
-               LEAVE('i', 0);
-               return 0;
-       }
-       
-       // Read only block
-       if(Length <= disk->BlockSize - Offset)
-       {
-               VFS_ReadAt( disk->FD, base+Offset, Length, Buffer);
-               LEAVE('X', Length);
-               return Length;
-       }
-       
-       // Read first block
-       remLen = Length;
-       VFS_ReadAt( disk->FD, base + Offset, disk->BlockSize - Offset, Buffer);
-       remLen -= disk->BlockSize - Offset;
-       Buffer += disk->BlockSize - Offset;
-       block ++;
-       
-       // Read middle blocks
-       while(remLen > disk->BlockSize)
-       {
-               base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
-               if(base == 0) {
-                       Warning("[EXT2 ] NULL Block Detected in INode 0x%llx", Node->Inode);
-                       LEAVE('i', 0);
-                       return 0;
-               }
-               VFS_ReadAt( disk->FD, base, disk->BlockSize, Buffer);
-               Buffer += disk->BlockSize;
-               remLen -= disk->BlockSize;
-               block ++;
-       }
-       
-       // Read last block
-       base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
-       VFS_ReadAt( disk->FD, base, remLen, Buffer);
-       
-       LEAVE('X', Length);
-       return Length;
-}
diff --git a/Modules/Filesystems/FS_Ext2/write.c b/Modules/Filesystems/FS_Ext2/write.c
deleted file mode 100644 (file)
index f3fdc6b..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Acess OS
- * Ext2 Driver Version 1
- */
-/**
- * \file write.c
- * \brief Second Extended Filesystem Driver
- * \todo Implement file full write support
- */
-#define DEBUG  1
-#define VERBOSE        0
-#include "ext2_common.h"
-
-// === PROTOYPES ===
-Uint64         Ext2_Write(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer);
-Uint32         Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock);
-
-// === CODE ===
-/**
- * \fn Uint64 Ext2_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
- * \brief Write to a file
- */
-Uint64 Ext2_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
-{
-       tExt2_Disk      *disk = Node->ImplPtr;
-       tExt2_Inode     inode;
-       Uint64  base;
-       Uint64  retLen;
-       Uint    block;
-       Uint64  allocSize;
-        int    bNewBlocks = 0;
-       
-       Debug_HexDump("Ext2_Write", Buffer, Length);
-       
-       Ext2_int_GetInode(Node, &inode);
-       
-       // Get the ammount of space already allocated
-       // - Round size up to block size
-       // - block size is a power of two, so this will work
-       allocSize = (inode.i_size + disk->BlockSize) & ~(disk->BlockSize-1);
-       
-       // Are we writing to inside the allocated space?
-       if( Offset < allocSize )
-       {
-               // Will we go out of it?
-               if(Offset + Length > allocSize) {
-                       bNewBlocks = 1;
-                       retLen = allocSize - Offset;
-               } else
-                       retLen = Length;
-               
-               // Within the allocated space
-               block = Offset / disk->BlockSize;
-               Offset %= disk->BlockSize;
-               base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
-               
-               // Write only block (if only one)
-               if(Offset + retLen <= disk->BlockSize) {
-                       VFS_WriteAt(disk->FD, base+Offset, retLen, Buffer);
-                       if(!bNewBlocks) return Length;
-                       goto addBlocks; // Ugh! A goto, but it seems unavoidable
-               }
-               
-               // Write First Block
-               VFS_WriteAt(disk->FD, base+Offset, disk->BlockSize-Offset, Buffer);
-               Buffer += disk->BlockSize-Offset;
-               retLen -= disk->BlockSize-Offset;
-               block ++;
-               
-               // Write middle blocks
-               while(retLen > disk->BlockSize)
-               {
-                       base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
-                       VFS_WriteAt(disk->FD, base, disk->BlockSize, Buffer);
-                       Buffer += disk->BlockSize;
-                       retLen -= disk->BlockSize;
-                       block ++;
-               }
-               
-               // Write last block
-               base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
-               VFS_WriteAt(disk->FD, base, retLen, Buffer);
-               if(!bNewBlocks) return Length;  // Writing in only allocated space
-       }
-       
-addBlocks:
-       ///\todo Implement block allocation
-       Warning("[EXT2] File extending is not yet supported");
-       
-       return 0;
-}
-
-/**
- * \fn Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock)
- * \brief Allocate a block from the best possible location
- * \param Disk EXT2 Disk Information Structure
- * \param PrevBlock    Previous block ID in the file
- */
-Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock)
-{
-        int    bpg = Disk->SuperBlock.s_blocks_per_group;
-       Uint    blockgroup = PrevBlock / bpg;
-       Uint    bitmap[Disk->BlockSize/sizeof(Uint)];
-       Uint    bitsperblock = 8*Disk->BlockSize;
-        int    i, j = 0;
-       Uint    block;
-       
-       // Are there any free blocks?
-       if(Disk->SuperBlock.s_free_blocks_count == 0)   return 0;
-       
-       if(Disk->Groups[blockgroup].bg_free_blocks_count > 0)
-       {
-               // Search block group's bitmap
-               for(i = 0; i < bpg; i++)
-               {
-                       // Get the block in the bitmap block
-                       j = i & (bitsperblock-1);
-                       
-                       // Read in if needed
-                       if(j == 0) {
-                               VFS_ReadAt(
-                                       Disk->FD,
-                                       (Uint64)Disk->Groups[blockgroup].bg_block_bitmap + i / bitsperblock,
-                                       Disk->BlockSize,
-                                       bitmap
-                                       );
-                       }
-                       
-                       // Fast Check
-                       if( bitmap[j/32] == -1 ) {
-                               j = (j + 31) & ~31;
-                               continue;
-                       }
-                       
-                       // Is the bit set?
-                       if( bitmap[j/32] & (1 << (j%32)) )
-                               continue;
-                       
-                       // Ooh! We found one
-                       break;
-               }
-               if( i < bpg ) {
-                       Warning("[EXT2 ] Inconsistency detected, Group Free Block count is non-zero when no free blocks exist");
-                       goto    checkAll;       // Search the entire filesystem for a free block
-                       // Goto needed for neatness
-               }
-               
-               // Mark as used
-               bitmap[j/32] |= (1 << (j%32));
-               VFS_WriteAt(
-                       Disk->FD,
-                       (Uint64)Disk->Groups[blockgroup].bg_block_bitmap + i / bitsperblock,
-                       Disk->BlockSize,
-                       bitmap
-                       );
-               block = i;
-               Disk->Groups[blockgroup].bg_free_blocks_count --;
-               #if EXT2_UPDATE_WRITEBACK
-               //Ext2_int_UpdateBlockGroup(blockgroup);
-               #endif
-       }
-       else
-       {
-       checkAll:
-               Warning("[EXT2 ] TODO - Implement using blocks outside the current block group");
-               return 0;
-       }
-       
-       // Reduce global count
-       Disk->SuperBlock.s_free_blocks_count --;
-       #if EXT2_UPDATE_WRITEBACK
-       Ext2_int_UpdateSuperblock(Disk);
-       #endif
-       
-       return block;
-}
diff --git a/Modules/Filesystems/FS_NFS/Makefile b/Modules/Filesystems/FS_NFS/Makefile
deleted file mode 100644 (file)
index 6fa2e6e..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#
-#
-
-OBJ = main.o
-NAME = FS_NFS
-
--include ../Makefile.tpl
diff --git a/Modules/Filesystems/FS_NFS/common.h b/Modules/Filesystems/FS_NFS/common.h
deleted file mode 100644 (file)
index d73592f..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Acess2 - NFS Driver
- * By John Hodge (thePowersGang)
- * This file is published under the terms of the Acess licence. See the
- * file COPYING for details.
- *
- * common.h - Common definitions
- */
-#ifndef _COMMON_H_
-#define _COMMON_H_
-
-typedef struct sNFS_Connection
-{
-        int    FD;
-       tIPAddr Host;
-       char    *Base;
-       tVFS_Node       Node;
-}      tNFS_Connection;
-
-#endif
diff --git a/Modules/Filesystems/FS_NFS/main.c b/Modules/Filesystems/FS_NFS/main.c
deleted file mode 100644 (file)
index 459945f..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Acess2 - NFS Driver
- * By John Hodge (thePowersGang)
- * This file is published under the terms of the Acess licence. See the
- * file COPYING for details.
- *
- * main.c - Driver core
- */
-#define DEBUG  1
-#define VERBOSE        0
-#include "common.h"
-#include <modules.h>
-
-// === PROTOTYPES ===
- int   NFS_Install(char **Arguments);
-tVFS_Node      *NFS_InitDevice(char *Devices, char **Options);
-void   NFS_Unmount(tVFS_Node *Node);
-
-// === GLOBALS ===
-MODULE_DEFINE(0, 0x32 /*v0.5*/, FS_NFS, NFS_Install, NULL);
-tVFS_Driver    gNFS_FSInfo = {"nfs", 0, NFS_InitDevice, NFS_Unmount, NULL};
-
-tNFS_Connection        *gpNFS_Connections;
-
-// === CODE ===
-/**
- * \brief Installs the NFS driver
- */
-int NFS_Install(char **Arguments)
-{
-       VFS_AddDriver( &gNFS_FSInfo );
-       return 1;
-}
-
-/**
- * \brief Mount a NFS share
- */
-tVFS_Node *NFS_InitDevice(char *Device, char **Options)
-{
-       char    *path, *host;
-       tNFS_Connection *conn;
-       
-       path = strchr( Device, ':' ) + 1;
-       host = strndup( Device, (int)(path-Device)-1 );
-       
-       conn = malloc( sizeof(tNFS_Connection) );
-       
-       if( !IPTools_GetAddress(host, &conn->IP) ) {
-               free(conn);
-               return NULL;
-       }
-       free(host);
-       
-       conn->FD = IPTools_OpenUdpClient( &conn->Host );
-       if(conn->FD == -1) {
-               free(conn);
-               return NULL;
-       }
-       
-       conn->Base = strdup( path );
-       conn->RootNode.ImplPtr = conn;
-       conn->RootNode.Flags = VFS_FFLAG_DIRECTORY;
-       
-       conn->RootNode.ReadDir = NFS_ReadDir;
-       conn->RootNode.FindDir = NFS_FindDir;
-       conn->RootNode.Close = NULL;
-       
-       return &conn->RootNode;
-}
-
-void NFS_Unmount(tVFS_Node *Node)
-{
-       
-}
diff --git a/Modules/Filesystems/InitRD/.gitignore b/Modules/Filesystems/InitRD/.gitignore
new file mode 100644 (file)
index 0000000..a311505
--- /dev/null
@@ -0,0 +1 @@
+files.c
diff --git a/Modules/Filesystems/InitRD/GenerateInitRD.php b/Modules/Filesystems/InitRD/GenerateInitRD.php
new file mode 100644 (file)
index 0000000..031ad59
--- /dev/null
@@ -0,0 +1,151 @@
+<?php
+$lGenDate = date("Y-m-d H:i");
+$gOutput = <<<EOF
+/*
+ * Acess2 InitRD
+ * InitRD Data
+ * Generated $lGenDate
+ */
+#include "initrd.h"
+
+EOF;
+
+$lines = file($argv[1]);
+
+$lDepth = 0;
+$lTree = array();
+$lStack = array( array("",array()) );
+foreach($lines as $line)
+{
+       $line = trim($line);
+       if(preg_match('/^Dir\s+"([^"]+)"\s+{$/', $line, $matches))
+       {
+               $new = array($matches[1], array());
+               array_push($lStack, $new);
+               $lDepth ++;
+               continue;
+       }
+       if($line == "}")
+       {
+               $lDepth --;
+               $lStack[$lDepth][1][] = array_pop($lStack);
+               continue;
+       }
+       if(preg_match('/^File\s+"([^"]+)"\s+"([^"]+)"$/', $line, $matches))
+       {
+               $lStack[$lDepth][1][] = array($matches[1], $matches[2]);
+               continue;
+       }
+       echo "ERROR: $line\n";
+       exit(0);
+}
+
+function hd($fp)
+{
+       return "0x".str_pad( dechex(ord(fgetc($fp))), 2, "0", STR_PAD_LEFT );
+}
+
+function ProcessFolder($prefix, $items)
+{
+       global  $gOutput;
+       foreach($items as $i=>$item)
+       {
+               if(is_array($item[1]))
+               {
+                       ProcessFolder("{$prefix}_{$i}", $item[1]);
+                       
+                       $gOutput .= "tInitRD_File {$prefix}_{$i}_entries[] = {\n";
+                       foreach($item[1] as $j=>$child)
+                       {
+                               if($j)  $gOutput .= ",\n";
+                               $gOutput .= "\t{\"".addslashes($child[0])."\",&{$prefix}_{$i}_{$j}}";
+                       }
+                       $gOutput .= "\n};\n";
+                       
+                       $size = count($item[1]);
+                       $gOutput .= <<<EOF
+tVFS_Node {$prefix}_{$i} = {
+       .NumACLs = 1,
+       .ACLs = &gVFS_ACL_EveryoneRX,
+       .Flags = VFS_FFLAG_DIRECTORY,
+       .Size = $size,
+       .ImplPtr = {$prefix}_{$i}_entries,
+       .ReadDir = InitRD_ReadDir,
+       .FindDir = InitRD_FindDir
+};
+
+EOF;
+               }
+               else {
+                       if(!file_exists($item[1])) {
+                               echo "ERROR: '{$item[1]}' does not exist\n", 
+                               exit(1);
+                       }
+                       $size = filesize($item[1]);
+                       
+                       $gOutput .= "Uint8 {$prefix}_{$i}_data[] = {\n";
+                       $fp = fopen($item[1], "rb");
+                       for( $j = 0; $j + 16 < $size; $j += 16 )
+                       {
+                               $gOutput .= "\t";
+                               $gOutput .= hd($fp).",".hd($fp).",";
+                               $gOutput .= hd($fp).",".hd($fp).",";
+                               $gOutput .= hd($fp).",".hd($fp).",";
+                               $gOutput .= hd($fp).",".hd($fp).",";
+                               $gOutput .= hd($fp).",".hd($fp).",";
+                               $gOutput .= hd($fp).",".hd($fp).",";
+                               $gOutput .= hd($fp).",".hd($fp).",";
+                               $gOutput .= hd($fp).",".hd($fp).",\n";
+                       }
+                       $gOutput .= "\t";
+                       for( ; $j < $size; $j ++ )
+                       {
+                               if( $j & 15 )   $gOutput .= ",";
+                               $gOutput .= hd($fp);
+                       }
+                       fclose($fp);
+                       $gOutput .= "\n};\n";
+                       $gOutput .= <<<EOF
+tVFS_Node {$prefix}_{$i} = {
+       .NumACLs = 1,
+       .ACLs = &gVFS_ACL_EveryoneRX,
+       .Flags = 0,
+       .Size = $size,
+       .ImplPtr = {$prefix}_{$i}_data,
+       .Read = InitRD_ReadFile
+};
+
+EOF;
+               }
+       }
+}
+
+//print_r($lStack);
+//exit(1);
+
+ProcessFolder("gInitRD_Files", $lStack[0][1]);
+
+$gOutput .= "tInitRD_File gInitRD_Root_Files[] = {\n";
+foreach($lStack[0][1] as $j=>$child)
+{
+       if($j)  $gOutput .= ",\n";
+       $gOutput .= "\t{\"".addslashes($child[0])."\",&gInitRD_Files_{$j}}";
+}
+$gOutput .= "\n};\n";
+$nRootFiles = count($lStack[0][1]);
+$gOutput .= <<<EOF
+tVFS_Node gInitRD_RootNode = {
+       .NumACLs = 1,
+       .ACLs = &gVFS_ACL_EveryoneRX,
+       .Flags = VFS_FFLAG_DIRECTORY,
+       .Size = $nRootFiles,
+       .ImplPtr = gInitRD_Root_Files,
+       .ReadDir = InitRD_ReadDir,
+       .FindDir = InitRD_FindDir
+};
+EOF;
+
+$fp = fopen($argv[2], "w");
+fputs($fp, $gOutput);
+fclose($fp);
+?>
diff --git a/Modules/Filesystems/InitRD/Makefile b/Modules/Filesystems/InitRD/Makefile
new file mode 100644 (file)
index 0000000..2c78bf1
--- /dev/null
@@ -0,0 +1,10 @@
+# InitRD Filesystem Driver
+#
+
+OBJ = main.o files.o
+NAME = InitRD
+
+-include ../Makefile.tpl
+
+files.c: GenerateInitRD.php files.lst
+       php GenerateInitRD.php files.lst files.c
diff --git a/Modules/Filesystems/InitRD/files.lst b/Modules/Filesystems/InitRD/files.lst
new file mode 100644 (file)
index 0000000..7ebee22
--- /dev/null
@@ -0,0 +1,19 @@
+Dir "SBin" {
+       File "init" "../../../Usermode/Applications/init"
+       File "login" "../../../Usermode/Applications/login"
+}
+Dir "Bin" {
+       File "CLIShell" "../../../Usermode/Applications/CLIShell"
+       File "ls" "../../../Usermode/Applications/ls"
+       File "cat" "../../../Usermode/Applications/cat"
+       File "mount" "../../../Usermode/Applications/mount"
+}
+Dir "Libs" {
+       File "ld-acess.so" "../../../Usermode/Libraries/ld-acess.so"
+       File "libacess.so" "../../../Usermode/Libraries/libacess.so"
+       File "libc.so.1" "../../../Usermode/Libraries/libc.so.1"
+       File "libgcc.so" "../../../Usermode/Libraries/libgcc.so"
+}
+Dir "Conf" {
+       File "BootConf.cfg" "../../../Usermode/Filesystem/Conf/BootConf.cfg"
+}
diff --git a/Modules/Filesystems/InitRD/initrd.h b/Modules/Filesystems/InitRD/initrd.h
new file mode 100644 (file)
index 0000000..8ae97ae
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ */
+#ifndef _INITRD_H_
+#define _INITRD_H_
+
+#include <acess.h>
+#include <vfs.h>
+
+typedef struct sInitRD_File
+{
+       char    *Name;
+       tVFS_Node       *Node;
+}      tInitRD_File;
+
+
+// === Functions ===
+extern Uint64  InitRD_ReadFile(tVFS_Node *Node, Uint64 Offset, Uint64 Size, void *Buffer);
+extern char    *InitRD_ReadDir(tVFS_Node *Node, int ID);
+extern tVFS_Node       *InitRD_FindDir(tVFS_Node *Node, char *Name);
+
+#endif
diff --git a/Modules/Filesystems/InitRD/main.c b/Modules/Filesystems/InitRD/main.c
new file mode 100644 (file)
index 0000000..08835bf
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Acess OS
+ * InitRD Driver Version 1
+ */
+#include "initrd.h"
+#include <modules.h>
+
+// === IMPORTS ==
+extern tVFS_Node       gInitRD_RootNode;
+
+// === PROTOTYPES ===
+ int   InitRD_Install(char **Arguments);
+tVFS_Node      *InitRD_InitDevice(char *Device, char **Arguments);
+void   InitRD_Unmount(tVFS_Node *Node);
+Uint64 InitRD_ReadFile(tVFS_Node *Node, Uint64 Offset, Uint64 Size, void *Buffer);
+char   *InitRD_ReadDir(tVFS_Node *Node, int ID);
+tVFS_Node      *InitRD_FindDir(tVFS_Node *Node, char *Name);
+
+// === GLOBALS ===
+MODULE_DEFINE(0, 0x0A, FS_InitRD, InitRD_Install, NULL);
+tVFS_Driver    gInitRD_FSInfo = {
+       "initrd", 0, InitRD_InitDevice, InitRD_Unmount, NULL
+       };
+
+/**
+ * \brief Register initrd with the kernel
+ */
+int InitRD_Install(char **Arguments)
+{
+       VFS_AddDriver( &gInitRD_FSInfo );
+       return MODULE_ERR_OK;
+}
+
+/**
+ * \brief Mount the InitRD
+ */
+tVFS_Node *InitRD_InitDevice(char *Device, char **Arguments)
+{
+       return &gInitRD_RootNode;
+}
+
+/**
+ * \brief Unmount the InitRD
+ */
+void InitRD_Unmount(tVFS_Node *Node)
+{
+}
+
+/**
+ * \brief Read from a file
+ */
+Uint64 InitRD_ReadFile(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
+{
+       if(Offset > Node->Size)
+               return 0;
+       if(Offset + Length > Node->Size)
+               Length = Node->Size - Offset;
+       
+       memcpy(Buffer, Node->ImplPtr+Offset, Length);
+       
+       return Length;
+}
+
+/**
+ * \brief Read from a directory
+ */
+char *InitRD_ReadDir(tVFS_Node *Node, int ID)
+{
+       tInitRD_File    *dir = Node->ImplPtr;
+       
+       if(ID >= Node->Size)
+               return NULL;
+       
+       return strdup(dir[ID].Name);
+}
+
+/**
+ * \brief Find an element in a directory
+ */
+tVFS_Node *InitRD_FindDir(tVFS_Node *Node, char *Name)
+{
+        int    i;
+       tInitRD_File    *dir = Node->ImplPtr;
+       
+       //Log("InirRD_FindDir: Name = '%s'", Name);
+       
+       for( i = 0; i < Node->Size; i++ )
+       {
+               if(strcmp(Name, dir[i].Name) == 0)
+                       return dir[i].Node;
+       }
+       
+       return NULL;
+}
index 80c6d4d..77dfc2c 100644 (file)
@@ -1 +1,2 @@
+CATEGORY = FS
 -include ../../Makefile.tpl
diff --git a/Modules/Filesystems/NFS/Makefile b/Modules/Filesystems/NFS/Makefile
new file mode 100644 (file)
index 0000000..0b2019f
--- /dev/null
@@ -0,0 +1,7 @@
+#
+#
+
+OBJ = main.o
+NAME = NFS
+
+-include ../Makefile.tpl
diff --git a/Modules/Filesystems/NFS/common.h b/Modules/Filesystems/NFS/common.h
new file mode 100644 (file)
index 0000000..d73592f
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Acess2 - NFS Driver
+ * By John Hodge (thePowersGang)
+ * This file is published under the terms of the Acess licence. See the
+ * file COPYING for details.
+ *
+ * common.h - Common definitions
+ */
+#ifndef _COMMON_H_
+#define _COMMON_H_
+
+typedef struct sNFS_Connection
+{
+        int    FD;
+       tIPAddr Host;
+       char    *Base;
+       tVFS_Node       Node;
+}      tNFS_Connection;
+
+#endif
diff --git a/Modules/Filesystems/NFS/main.c b/Modules/Filesystems/NFS/main.c
new file mode 100644 (file)
index 0000000..459945f
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Acess2 - NFS Driver
+ * By John Hodge (thePowersGang)
+ * This file is published under the terms of the Acess licence. See the
+ * file COPYING for details.
+ *
+ * main.c - Driver core
+ */
+#define DEBUG  1
+#define VERBOSE        0
+#include "common.h"
+#include <modules.h>
+
+// === PROTOTYPES ===
+ int   NFS_Install(char **Arguments);
+tVFS_Node      *NFS_InitDevice(char *Devices, char **Options);
+void   NFS_Unmount(tVFS_Node *Node);
+
+// === GLOBALS ===
+MODULE_DEFINE(0, 0x32 /*v0.5*/, FS_NFS, NFS_Install, NULL);
+tVFS_Driver    gNFS_FSInfo = {"nfs", 0, NFS_InitDevice, NFS_Unmount, NULL};
+
+tNFS_Connection        *gpNFS_Connections;
+
+// === CODE ===
+/**
+ * \brief Installs the NFS driver
+ */
+int NFS_Install(char **Arguments)
+{
+       VFS_AddDriver( &gNFS_FSInfo );
+       return 1;
+}
+
+/**
+ * \brief Mount a NFS share
+ */
+tVFS_Node *NFS_InitDevice(char *Device, char **Options)
+{
+       char    *path, *host;
+       tNFS_Connection *conn;
+       
+       path = strchr( Device, ':' ) + 1;
+       host = strndup( Device, (int)(path-Device)-1 );
+       
+       conn = malloc( sizeof(tNFS_Connection) );
+       
+       if( !IPTools_GetAddress(host, &conn->IP) ) {
+               free(conn);
+               return NULL;
+       }
+       free(host);
+       
+       conn->FD = IPTools_OpenUdpClient( &conn->Host );
+       if(conn->FD == -1) {
+               free(conn);
+               return NULL;
+       }
+       
+       conn->Base = strdup( path );
+       conn->RootNode.ImplPtr = conn;
+       conn->RootNode.Flags = VFS_FFLAG_DIRECTORY;
+       
+       conn->RootNode.ReadDir = NFS_ReadDir;
+       conn->RootNode.FindDir = NFS_FindDir;
+       conn->RootNode.Close = NULL;
+       
+       return &conn->RootNode;
+}
+
+void NFS_Unmount(tVFS_Node *Node)
+{
+       
+}
index ec10f39..cedc0b3 100644 (file)
@@ -90,7 +90,7 @@ tMacAddr ARP_Resolve4(tInterface *Interface, tIPv4 Address)
        lastID = giARP_LastUpdateID;
        
        // Create request
-       Log("[ARP4 ] Asking for address %i.%i.%i.%i",
+       Log_Log("ARP4", "Asking for address %i.%i.%i.%i",
                Address.B[0], Address.B[1], Address.B[2], Address.B[3]
                );
        req.HWType = htons(0x0001);     // Ethernet
@@ -152,7 +152,7 @@ void ARP_UpdateCache4(tIPv4 SWAddr, tMacAddr HWAddr)
                gaARP_Cache4[i].IP = SWAddr;
        }
        
-       Log("[ARP  ] Caching %i.%i.%i.%i (%02x:%02x:%02x:%02x:%02x:%02x) in %i",
+       Log_Log("ARP4", "Caching %i.%i.%i.%i (%02x:%02x:%02x:%02x:%02x:%02x) in %i",
                SWAddr.B[0], SWAddr.B[1], SWAddr.B[2], SWAddr.B[3],
                HWAddr.B[0], HWAddr.B[1], HWAddr.B[2], HWAddr.B[3], HWAddr.B[4], HWAddr.B[5],
                i
@@ -210,19 +210,25 @@ void ARP_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffe
        
        // Sanity Check Packet
        if( Length < sizeof(tArpRequest4) ) {
-               Log("[ARP  ] Recieved undersized packet");
+               Log_Log("ARP", "Recieved undersized packet");
                return ;
        }
        if( ntohs(req4->Type) != 0x0800 ) {
-               Log("[ARP  ] Recieved a packet with a bad type 0x%x", ntohs(req4->Type));
+               Log_Log("ARP", "Recieved a packet with a bad type 0x%x", ntohs(req4->Type));
                return ;
        }
        if( req4->HWSize != 6 ) {
-               Log("[ARP  ] Recieved a packet with HWSize != 6 (%i)", req4->HWSize);
+               Log_Log("ARP", "Recieved a packet with HWSize != 6 (%i)", req4->HWSize);
                return;
        }
        if( !MAC_EQU(req4->SourceMac, From) ) {
-               Log("[ARP  ] ARP spoofing detected", req4->HWSize);
+               Log_Log("ARP", "ARP spoofing detected "
+                       "(%02x%02x:%02x%02x:%02x%02x != %02x%02x:%02x%02x:%02x%02x)",
+                       req4->SourceMac.B[0], req4->SourceMac.B[1], req4->SourceMac.B[2],
+                       req4->SourceMac.B[3], req4->SourceMac.B[4], req4->SourceMac.B[5],
+                       From.B[0], From.B[1], From.B[2],
+                       From.B[3], From.B[4], From.B[5]
+                       );
                return;
        }
        
index 77bc691..088caaa 100644 (file)
@@ -111,7 +111,7 @@ int ICMP_Ping(tInterface *Interface, tIPv4 Addr)
                {
                        if(gICMP_PingSlots[i].Interface == NULL)        break;
                }
-               if(gICMP_PingSlots[i].Interface == NULL)        break;
+               if( i < PING_SLOTS )    break;
                Threads_Yield();
        }
        gICMP_PingSlots[i].Interface = Interface;
index 54d8fb8..78faf66 100644 (file)
@@ -61,6 +61,7 @@ struct sAdapter {
         int    NRef;
        
        tMacAddr        MacAddr;
+        int    DeviceLen;
        char    Device[];
 };
 
@@ -81,9 +82,9 @@ static const tMacAddr cMAC_BROADCAST = {{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}};
 #define IP4_SET(t,v)   (t).L = (v).L;
 #define IP6_SET(t,v)   memcpy(&(t),&(v),sizeof(tIPv6))
 
-#define MAC_EQU(a,b)   memcmp(&(a),&(b),sizeof(tMacAddr))
+#define MAC_EQU(a,b)   (memcmp(&(a),&(b),sizeof(tMacAddr))==0)
 #define IP4_EQU(a,b)   ((a).L==(b).L)
-#define IP6_EQU(a,b)   memcmp(&(a),&(b),sizeof(tIPv6))
+#define IP6_EQU(a,b)   (memcmp(&(a),&(b),sizeof(tIPv6))==0)
 
 // === FUNCTIONS ===
 #define htonb(v)       (v)
index 89f5671..ae1c123 100644 (file)
@@ -85,7 +85,7 @@ int IPv4_SendPacket(tInterface *Iface, tIPv4 Address, int Protocol, int ID, int
        hdr->Destination = Address;
        hdr->HeaderChecksum = IPv4_Checksum(hdr, sizeof(tIPv4Header));
        
-       Log("[IPv4 ] Sending packet to %i.%i.%i.%i",
+       Log_Log("IPv4", "Sending packet to %i.%i.%i.%i",
                Address.B[0], Address.B[1], Address.B[2], Address.B[3]);
        Link_SendPacket(Iface->Adapter, IPV4_ETHERNET_ID, to, bufSize, buf);
        return 1;
@@ -103,23 +103,23 @@ void IPv4_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buff
         int    dataLength;
        if(Length < sizeof(tIPv4Header))        return;
        
-       //Log("[IPv4 ] Version = %i", hdr->Version);
-       Log("[IPv4 ] HeaderLength = %i", hdr->HeaderLength);
-       Log("[IPv4 ] DiffServices = %i", hdr->DiffServices);
-       Log("[IPv4 ] TotalLength = %i", ntohs(hdr->TotalLength) );
-       //Log("[IPv4 ] Identifcation = %i", ntohs(hdr->Identifcation) );
-       //Log("[IPv4 ] TTL = %i", hdr->TTL );
-       Log("[IPv4 ] Protocol = %i", hdr->Protocol );
-       //Log("[IPv4 ] HeaderChecksum = 0x%x", ntohs(hdr->HeaderChecksum) );
-       Log("[IPv4 ] Source = %i.%i.%i.%i",
+       //Log_Log("IPv4", "Version = %i", hdr->Version);
+       Log_Log("IPv4", "HeaderLength = %i", hdr->HeaderLength);
+       Log_Log("IPv4", "DiffServices = %i", hdr->DiffServices);
+       Log_Log("IPv4", "TotalLength = %i", ntohs(hdr->TotalLength) );
+       //Log_Log("IPv4", "Identifcation = %i", ntohs(hdr->Identifcation) );
+       //Log_Log("IPv4", "TTL = %i", hdr->TTL );
+       Log_Log("IPv4", "Protocol = %i", hdr->Protocol );
+       //Log_Log("IPv4", "HeaderChecksum = 0x%x", ntohs(hdr->HeaderChecksum) );
+       Log_Log("IPv4", "Source = %i.%i.%i.%i",
                hdr->Source.B[0], hdr->Source.B[1], hdr->Source.B[2], hdr->Source.B[3] );
-       Log("[IPv4 ] Destination = %i.%i.%i.%i",
+       Log_Log("IPv4", "Destination = %i.%i.%i.%i",
                hdr->Destination.B[0], hdr->Destination.B[1],
                hdr->Destination.B[2], hdr->Destination.B[3] );
        
        // Check that the version IS IPv4
        if(hdr->Version != 4) {
-               Log("[IPv4 ] hdr->Version(%i) != 4", hdr->Version);
+               Log_Log("IPv4", "hdr->Version(%i) != 4", hdr->Version);
                return;
        }
        
@@ -128,14 +128,14 @@ void IPv4_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buff
        
        // Check Packet length
        if( ntohs(hdr->TotalLength) > Length) {
-               Log("[IPv4 ] hdr->TotalLength(%i) > Length(%i)", ntohs(hdr->TotalLength), Length);
+               Log_Log("IPv4", "hdr->TotalLength(%i) > Length(%i)", ntohs(hdr->TotalLength), Length);
                return;
        }
        
        // Get Interface (allowing broadcasts)
        iface = IPv4_GetInterface(Adapter, hdr->Destination, 1);
        if(!iface) {
-               Log("[IPv4 ] Ignoring Packet (Not for us)");
+               Log_Log("IPv4", "Ignoring Packet (Not for us)");
                return; // Not for us? Well, let's ignore it
        }
        
@@ -149,7 +149,7 @@ void IPv4_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buff
        if( gaIPv4_Callbacks[hdr->Protocol] )
                gaIPv4_Callbacks[hdr->Protocol] (iface, &hdr->Source, dataLength, data);
        else
-               Log("[IPv4 ] Unknown Protocol %i", hdr->Protocol);
+               Log_Log("IPv4", "Unknown Protocol %i", hdr->Protocol);
 }
 
 /**
index 0191efb..6cdb2bc 100644 (file)
@@ -41,7 +41,7 @@ void Link_RegisterType(Uint16 Type, tPacketCallback Callback)
        for( i = giRegisteredTypes; i -- ; )
        {
                if(gaRegisteredTypes[i].Type == Type) {
-                       Warning("[NET  ] Attempt to register 0x%x twice", Type);
+                       Log_Warning("NET", "Attempt to register 0x%x twice", Type);
                        return ;
                }
                // Ooh! Free slot!
@@ -52,7 +52,7 @@ void Link_RegisterType(Uint16 Type, tPacketCallback Callback)
        {
                tmp = realloc(gaRegisteredTypes, (giRegisteredTypes+1)*sizeof(*gaRegisteredTypes));
                if(!tmp) {
-                       Warning("[NET  ] Out of heap space!");
+                       Log_Warning("NET", "Out of heap space!");
                        return ;
                }
                i = giRegisteredTypes;
@@ -74,7 +74,7 @@ void Link_SendPacket(tAdapter *Adapter, Uint16 Type, tMacAddr To, int Length, vo
        Uint8   buf[bufSize];   // dynamic stack arrays ftw!
        tEthernetHeader *hdr = (void*)buf;
        
-       Log("[NET  ] Sending %i bytes to %02x:%02x:%02x:%02x:%02x:%02x (Type 0x%x)",
+       Log_Log("NET", "Sending %i bytes to %02x:%02x:%02x:%02x:%02x:%02x (Type 0x%x)",
                Length, To.B[0], To.B[1], To.B[2], To.B[3], To.B[4], To.B[5], Type);
        
        hdr->Dest = To;
@@ -98,12 +98,12 @@ void Link_WatchDevice(tAdapter *Adapter)
         int    tid = Proc_SpawnWorker();       // Create a new worker thread
        
        if(tid < 0) {
-               Warning("[NET  ] Unable to create watcher thread for '%s'", Adapter->Device);
+               Log_Warning("NET", "Unable to create watcher thread for '%s'", Adapter->Device);
                return ;
        }
        
        if(tid > 0) {
-               Log("[NET  ] Watching '%s' using tid %i", Adapter->Device, tid);
+               Log_Log("NET", "Watching '%s' using tid %i", Adapter->Device, tid);
                return ;
        }
        
@@ -123,20 +123,20 @@ void Link_WatchDevice(tAdapter *Adapter)
                if(ret == -1)   break;
                
                if(ret <= sizeof(tEthernetHeader)) {
-                       Log("[NET  ] Recieved an undersized packet");
+                       Log_Log("NET", "Recieved an undersized packet");
                        continue;
                }
                
-               Log("[NET  ] Packet from %02x:%02x:%02x:%02x:%02x:%02x",
+               Log_Log("NET", "Packet from %02x:%02x:%02x:%02x:%02x:%02x",
                        hdr->Src.B[0], hdr->Src.B[1], hdr->Src.B[2],
                        hdr->Src.B[3], hdr->Src.B[4], hdr->Src.B[5]
                        );
-               Log("[NET  ] to %02x:%02x:%02x:%02x:%02x:%02x",
+               Log_Log("NET", "to %02x:%02x:%02x:%02x:%02x:%02x",
                        hdr->Dest.B[0], hdr->Dest.B[1], hdr->Dest.B[2],
                        hdr->Dest.B[3], hdr->Dest.B[4], hdr->Dest.B[5]
                        );
                checksum = *(Uint32*)&hdr->Data[ret-sizeof(tEthernetHeader)-4];
-               Log("[NET  ] Checksum 0x%08x", checksum);
+               Log_Log("NET", "Checksum 0x%08x", checksum);
                
                // Check if there is a registered callback for this packet type
                for( i = giRegisteredTypes; i--; )
@@ -145,7 +145,7 @@ void Link_WatchDevice(tAdapter *Adapter)
                }
                // No? Ignore it
                if( i == -1 ) {
-                       Log("[NET  ] Unregistered type 0x%x", ntohs(hdr->Type));
+                       Log_Log("NET", "Unregistered type 0x%x", ntohs(hdr->Type));
                        continue;
                }
                
@@ -158,7 +158,7 @@ void Link_WatchDevice(tAdapter *Adapter)
                        );
        }
        
-       Log("[NET  ] Watcher terminated (file closed)");
+       Log_Log("NET", "Watcher terminated (file closed)");
 }
 
 // From http://www.cl.cam.ac.uk/research/srg/bluebook/21/crc/node6.html
index 6b6f8a9..6b75b77 100644 (file)
@@ -89,7 +89,7 @@ int IPStack_Install(char **Arguments)
        
        DevFS_AddDevice( &gIP_DriverInfo );
        
-       return 1;
+       return MODULE_ERR_OK;
 }
 
 /**
@@ -97,7 +97,7 @@ int IPStack_Install(char **Arguments)
  */
 int IPStack_AddFile(tSocketFile *File)
 {
-       Log("IPStack_AddFile: %s", File->Name);
+       Log_Log("IPStack", "Added file '%s'", File->Name);
        File->Next = gIP_FileTemplates;
        gIP_FileTemplates = File;
        return 0;
@@ -231,7 +231,6 @@ char *IPStack_Iface_ReadDir(tVFS_Node *Node, int Pos)
 {
        tSocketFile     *file = gIP_FileTemplates;
        while(Pos-- && file) {
-               Log("IPStack_Iface_ReadDir: %s", file->Name);
                file = file->Next;
        }
        
@@ -251,7 +250,6 @@ tVFS_Node *IPStack_Iface_FindDir(tVFS_Node *Node, char *Name)
        for(;file;file = file->Next)
        {
                if( strcmp(file->Name, Name) == 0 )     break;
-               Log("IPStack_Iface_FindDir: strcmp('%s', '%s')", file->Name, Name);
        }
        if(!file)       return NULL;
        
@@ -268,6 +266,7 @@ static const char *casIOCtls_Iface[] = {
        "get_address", "set_address",
        "getset_subnet",
        "get_gateway", "set_gateway",
+       "get_device",
        "ping",
        NULL
        };
@@ -465,11 +464,23 @@ int IPStack_Iface_IOCtl(tVFS_Node *Node, int ID, void *Data)
                }
                break;
        
+       /*
+        * get_device
+        * - Gets the name of the attached device
+        */
+       case 10:
+               if( Data == NULL )
+                       LEAVE_RET('i', iface->Adapter->DeviceLen);
+               if( !CheckMem( Data, iface->Adapter->DeviceLen+1 ) )
+                       LEAVE_RET('i', -1);
+               strcpy( Data, iface->Adapter->Device );
+               return iface->Adapter->DeviceLen;
+       
        /*
         * ping
         * - Send an ICMP Echo
         */
-       case 10:
+       case 11:
                switch(iface->Type)
                {
                case 0:
@@ -500,9 +511,12 @@ int IPStack_Iface_IOCtl(tVFS_Node *Node, int ID, void *Data)
 int IPStack_AddInterface(char *Device)
 {
        tInterface      *iface;
+       tAdapter        *card;
        
        ENTER("sDevice", Device);
        
+       card = IPStack_GetAdapter(Device);
+       
        iface = malloc(sizeof(tInterface));
        if(!iface) {
                LEAVE('i', -2);
@@ -514,7 +528,6 @@ int IPStack_AddInterface(char *Device)
        
        // Create Node
        iface->Node.ImplPtr = iface;
-       iface->Node.ImplInt = giIP_NextIfaceId++;
        iface->Node.Flags = VFS_FFLAG_DIRECTORY;
        iface->Node.Size = -1;
        iface->Node.NumACLs = 1;
@@ -534,6 +547,10 @@ int IPStack_AddInterface(char *Device)
                return -1;      // Return ERR_YOUFAIL
        }
        
+       // Delay setting ImplInt until after the adapter is opened
+       // Keeps things simple
+       iface->Node.ImplInt = giIP_NextIfaceId++;
+       
        // Append to list
        LOCK( &glIP_Interfaces );
        if( gIP_Interfaces ) {
@@ -588,6 +605,7 @@ tAdapter *IPStack_GetAdapter(char *Path)
        // Fill Structure
        strcpy( dev->Device, Path );
        dev->NRef = 1;
+       dev->DeviceLen = strlen(Path);
        
        // Open Device
        dev->DeviceFD = VFS_Open( dev->Device, VFS_OPENFLAG_READ|VFS_OPENFLAG_WRITE );
index fef9065..e7cded3 100644 (file)
@@ -73,7 +73,7 @@ void TCP_StartConnection(tTCPConnection *Conn)
        hdr.SequenceNumber = Conn->NextSequenceSend;
        hdr.DataOffset = (sizeof(tTCPHeader)/4) << 4;
        hdr.Flags = TCP_FLAG_SYN;
-       hdr.WindowSize = 0;     // TODO
+       hdr.WindowSize = 0xFFFF;        // Max
        hdr.Checksum = 0;       // TODO
        hdr.UrgentPointer = 0;
        
@@ -121,24 +121,24 @@ void TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffe
        tTCPListener    *srv;
        tTCPConnection  *conn;
 
-       Log("[TCP  ] SourcePort = %i, DestPort = %i",
+       Log_Log("TCP", "SourcePort = %i, DestPort = %i",
                ntohs(hdr->SourcePort), ntohs(hdr->DestPort));
-       Log("[TCP  ] SequenceNumber = 0x%x", ntohl(hdr->SequenceNumber));
-       Log("[TCP  ] AcknowlegementNumber = 0x%x", ntohl(hdr->AcknowlegementNumber));
-       Log("[TCP  ] DataOffset = %i", hdr->DataOffset >> 4);
-       Log("[TCP  ] Flags = {");
-       Log("[TCP  ]   CWR = %B, ECE = %B",
+       Log_Log("TCP", "SequenceNumber = 0x%x", ntohl(hdr->SequenceNumber));
+       Log_Log("TCP", "AcknowlegementNumber = 0x%x", ntohl(hdr->AcknowlegementNumber));
+       Log_Log("TCP", "DataOffset = %i", hdr->DataOffset >> 4);
+       Log_Log("TCP", "Flags = {");
+       Log_Log("TCP", "  CWR = %B, ECE = %B",
                !!(hdr->Flags & TCP_FLAG_CWR), !!(hdr->Flags & TCP_FLAG_ECE));
-       Log("[TCP  ]   URG = %B, ACK = %B",
+       Log_Log("TCP", "  URG = %B, ACK = %B",
                !!(hdr->Flags & TCP_FLAG_URG), !!(hdr->Flags & TCP_FLAG_ACK));
-       Log("[TCP  ]   PSH = %B, RST = %B",
+       Log_Log("TCP", "  PSH = %B, RST = %B",
                !!(hdr->Flags & TCP_FLAG_PSH), !!(hdr->Flags & TCP_FLAG_RST));
-       Log("[TCP  ]   SYN = %B, FIN = %B",
+       Log_Log("TCP", "  SYN = %B, FIN = %B",
                !!(hdr->Flags & TCP_FLAG_SYN), !!(hdr->Flags & TCP_FLAG_FIN));
-       Log("[TCP  ] }");
-       Log("[TCP  ] WindowSize = %i", htons(hdr->WindowSize));
-       Log("[TCP  ] Checksum = 0x%x", htons(hdr->Checksum));
-       Log("[TCP  ] UrgentPointer = 0x%x", htons(hdr->UrgentPointer));
+       Log_Log("TCP", "}");
+       Log_Log("TCP", "WindowSize = %i", htons(hdr->WindowSize));
+       Log_Log("TCP", "Checksum = 0x%x", htons(hdr->Checksum));
+       Log_Log("TCP", "UrgentPointer = 0x%x", htons(hdr->UrgentPointer));
 
        if( Length > (hdr->DataOffset >> 4)*4 )
        {
@@ -160,17 +160,17 @@ void TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffe
                        // Check the destination port
                        if(srv->Port != htons(hdr->DestPort))   continue;
                        
-                       Log("[TCP  ] Matches server %p", srv);
+                       Log_Log("TCP", "Matches server %p", srv);
                        // Is this in an established connection?
                        for( conn = srv->Connections; conn; conn = conn->Next )
                        {
-                               Log("[TCP  ] conn->Interface(%p) == Interface(%p)",
+                               Log_Log("TCP", "conn->Interface(%p) == Interface(%p)",
                                        conn->Interface, Interface);
                                // Check that it is coming in on the same interface
                                if(conn->Interface != Interface)        continue;
 
                                // Check Source Port
-                               Log("[TCP  ] conn->RemotePort(%i) == hdr->SourcePort(%i)",
+                               Log_Log("TCP", "conn->RemotePort(%i) == hdr->SourcePort(%i)",
                                        conn->RemotePort, ntohs(hdr->SourcePort));
                                if(conn->RemotePort != ntohs(hdr->SourcePort))  continue;
 
@@ -180,17 +180,17 @@ void TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffe
                                if(conn->Interface->Type == 4 && !IP4_EQU(conn->RemoteIP.v4, *(tIPv4*)Address))
                                        continue;
 
-                               Log("[TCP  ] Matches connection %p", conn);
+                               Log_Log("TCP", "Matches connection %p", conn);
                                // We have a response!
                                TCP_INT_HandleConnectionPacket(conn, hdr, Length);
 
                                return;
                        }
 
-                       Log("[TCP  ] Opening Connection");
+                       Log_Log("TCP", "Opening Connection");
                        // Open a new connection (well, check that it's a SYN)
                        if(hdr->Flags != TCP_FLAG_SYN) {
-                               Log("[TCP  ] Packet is not a SYN");
+                               Log_Log("TCP", "Packet is not a SYN");
                                return ;
                        }
                        
@@ -270,7 +270,7 @@ void TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffe
                }
        }
        
-       Log("[TCP  ] No Match");
+       Log_Log("TCP", "No Match");
 }
 
 /**
@@ -291,11 +291,11 @@ void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Head
        
        // Get length of data
        dataLen = Length - (Header->DataOffset>>4)*4;
-       Log("[TCP  ] HandleConnectionPacket - dataLen = %i", dataLen);
+       Log_Log("TCP", "HandleConnectionPacket - dataLen = %i", dataLen);
        
        if(Header->Flags & TCP_FLAG_ACK) {
                // TODO: Process an ACKed Packet
-               Log("[TCP  ] Conn %p, Packet 0x%x ACKed", Connection, Header->AcknowlegementNumber);
+               Log_Log("TCP", "Conn %p, Packet 0x%x ACKed", Connection, Header->AcknowlegementNumber);
        }
        
        if(dataLen == 0)        return ;
@@ -315,9 +315,9 @@ void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Head
        // Is this packet the next expected packet?
        if( pkt->Sequence != Connection->NextSequenceRcv )
        {
-               tTCPStoredPacket        *tmp, *prev;
+               tTCPStoredPacket        *tmp, *prev = NULL;
                
-               Log("[TCP  ] Out of sequence packet (0x%08x != 0x%08x)",
+               Log_Log("TCP", "Out of sequence packet (0x%08x != 0x%08x)",
                        pkt->Sequence, Connection->NextSequenceRcv);
                
                // No? Well, let's cache it and look at it later
@@ -339,20 +339,23 @@ void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Head
        {
                // Ooh, Goodie! Add it to the recieved list
                TCP_INT_AppendRecieved(Connection, pkt);
-               Connection->NextSequenceRcv ++;
+               if(dataLen)
+                       Connection->NextSequenceRcv += dataLen;
+               else
+                       Connection->NextSequenceRcv += 1;
                
                // TODO: This should be moved out of the watcher thread,
                // so that a single lost packet on one connection doesn't cause
                // all connections on the interface to lag.
                TCP_INT_UpdateRecievedFromFuture(Connection);
-       }
        
-       // TODO: Check ACK code validity
-       Header->AcknowlegementNumber = ntohl(pkt->Sequence);
-       Header->SequenceNumber = ntohl(Connection->NextSequenceSend);
-       Header->Flags &= TCP_FLAG_SYN;
-       Header->Flags = TCP_FLAG_ACK;
-       TCP_SendPacket( Connection, sizeof(tTCPHeader), Header );
+               // TODO: Check ACK code validity
+               Header->AcknowlegementNumber = ntohl(pkt->Sequence) + dataLen;
+               Header->SequenceNumber = ntohl(Connection->NextSequenceSend);
+               Header->Flags &= TCP_FLAG_SYN;
+               Header->Flags = TCP_FLAG_ACK;
+               TCP_SendPacket( Connection, sizeof(tTCPHeader), Header );
+       }
 }
 
 /**
@@ -477,7 +480,16 @@ int TCP_DeallocatePort(Uint16 Port)
 // --- Server
 tVFS_Node *TCP_Server_Init(tInterface *Interface)
 {
-       tTCPListener    *srv = malloc( sizeof(tTCPListener) );
+       tTCPListener    *srv;
+       
+       srv = malloc( sizeof(tTCPListener) );
+
+       Log_Debug("TCP", "srv = %p", srv);
+
+       if( srv == NULL ) {
+               Log_Warning("TCP", "malloc failed for listener (%i) bytes", sizeof(tTCPListener));
+               return NULL;
+       }
 
        srv->Interface = Interface;
        srv->Port = 0;
@@ -514,7 +526,7 @@ char *TCP_Server_ReadDir(tVFS_Node *Node, int Pos)
        tTCPConnection  *conn;
        char    *ret;
 
-       Log("[TCP  ] Thread %i waiting for a connection", Threads_GetTID());
+       Log_Log("TCP", "Thread %i waiting for a connection", Threads_GetTID());
        for(;;)
        {
                LOCK( &srv->lConnections );
@@ -602,7 +614,7 @@ int TCP_Server_IOCtl(tVFS_Node *Node, int ID, void *Data)
                else    // Else, mark this as used
                        TCP_AllocatePort(srv->Port);
                
-               Log("[TCP  ] Server %p listening on port %i", srv, srv->Port);
+               Log_Log("TCP", "Server %p listening on port %i", srv, srv->Port);
                
                return srv->Port;
        }
diff --git a/Modules/Interfaces/EDI/Makefile b/Modules/Interfaces/EDI/Makefile
new file mode 100644 (file)
index 0000000..a93a8b7
--- /dev/null
@@ -0,0 +1,10 @@
+# 
+# EDI - Extensible Driver Interface
+# 
+# Acess Interface
+
+
+OBJ = main.o edi.o
+NAME = EDI
+
+-include ../Makefile.tpl
diff --git a/Modules/Interfaces/EDI/edi/acess-edi.h b/Modules/Interfaces/EDI/edi/acess-edi.h
new file mode 100644 (file)
index 0000000..4071388
--- /dev/null
@@ -0,0 +1,41 @@
+/*! \file acess-edi.h
+ * \brief Acess Specific EDI Objects
+ * 
+ * Contains documentation and information for
+ * - Timers
+ */
+
+/* Copyright (c)  2006  John Hodge
+ * Permission is granted to copy, distribute and/or modify this document
+ * under the terms of the GNU Free Documentation License, Version 1.2
+ * or any later version published by the Free Software Foundation;
+ * with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
+ * Texts.  A copy of the license is included in the file entitled "COPYING". */
+
+#ifndef ACESS_EDI_H
+#define ACESS_EDI_H
+
+#include "edi_objects.h"
+
+/// \brief Name of Acess EDI Time Class
+#define        ACESS_TIMER_CLASS       "ACESSEDI-TIMER"
+
+#ifndef IMPLEMENTING_EDI
+/*! \brief int32_t ACESSEDI-TIMER.init_timer(uint32_t Delay, void (*Callback)(int), int Arg);
+ *
+ * Takes a timer pointer and intialises the timer object to fire after \a Delay ms
+ * When the timer fires, \a Callback is called with \a Arg passed to it.
+ */
+EDI_DEFVAR int32_t (*init_timer)(object_pointer port_object, uint32_t Delay, void (*fcn)(int), int arg);
+
+/*! \brief void ACESSEDI-TIMER.disable_timer();
+ * 
+ * Disables the timer and prevents it from firing
+ * After this has been called, the timer can then be initialised again.
+ */
+EDI_DEFVAR void (*disable_timer)(object_pointer port_object);
+
+
+#endif // defined(IMPLEMENTING_EDI)
+
+#endif
diff --git a/Modules/Interfaces/EDI/edi/edi.h b/Modules/Interfaces/EDI/edi/edi.h
new file mode 100644 (file)
index 0000000..273f7a3
--- /dev/null
@@ -0,0 +1,114 @@
+#ifndef EDI_H
+
+/* Copyright (c)  2006  Eli Gottlieb.
+ * Permission is granted to copy, distribute and/or modify this document
+ * under the terms of the GNU Free Documentation License, Version 1.2
+ * or any later version published by the Free Software Foundation;
+ * with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
+ * Texts.  A copy of the license is included in the file entitled "COPYING". */
+
+#define EDI_H
+/*! \file edi.h
+ * \brief The unitive EDI header to include others, start EDI, and stop EDI.
+ *
+ * Data structures and algorithms this header represents:
+ *     DATA STRUCTURE: CLASS QUOTAS - The runtime and the driver have the right to set a quota on how many objects of a given class
+ * owned by that party the other may construct.  These quotas are kept internally by the driver or runtime, are optional and are
+ * exposed to the other party via the quota() function (for quotas of runtime-owned classes) and the k_quota() function pointer given
+ * to the runtime by the driver.
+ *
+ *     ALGORITHMS: INITIALIZATION AND SHUTDOWN - On initialization of the runtime's EDI environment for this driver it calls the
+ * driver's driver_init() routine (which must match driver_init_t) to initialize the driver with a list of EDI objects the runtime
+ * thinks the driver should run with.  The driver then initializes.  This can include calling edi_negotiate_resources() to try and
+ * obtain more or different objects.  Eventually driver_init() returns an edi_initialization_t structure containing its quota
+ * function and the list of classes belonging to the driver which the runtime can construct.  Either the driver or the runtime can
+ * shut down EDI by calling edi_shutdown(), which in turn calls the driver's driver_finish() routine.  On shutdown all objects, of
+ * classes belonging to both the runtime and driver, are destroyed. */
+
+#include "edi_objects.h"
+#include "edi_dma_streams.h"
+#include "edi_pthreads.h"
+#include "edi_port_io.h"
+#include "edi_memory_mapping.h"
+#include "edi_devices.h"
+#include "edi_interrupts.h"
+
+/*! \brief A pointer to a function the runtime can call if it fails to construct one of the driver's classes to find out what the
+ * runtime's quota is for that class.
+ *
+ * A pointer to a function which takes an edi_string_t as a parameter and returns in int32_t.  This function follows the same
+ * semantics as the quota() function, returning the number of objects of the given class that can be constructed, -1 for infinity or
+ * -2 for an erroneous class name.  It is used to tell the runtime the location of such a function in the driver so that the runtime
+ * can check quotas on driver-owned classes. */
+typedef int32_t (*k_quota_t)(edi_string_t resource_class);
+/*!\struct edi_initialization_t
+ * \brief Structure containing driver classes available to the runtime and the driver's quota function after the driver has initialized. 
+ *
+ * Structure containing driver classes available to runtime, the driver's quota function and the driver's name provided to the runtime
+ * after the driver has initialized.  driver_bus, vendor_id, and device_id are all optional fields which coders should consider
+ * supplementary information.  Kernels can require these fields if they so please, but doing so for devices which don't run on a Vendor
+ * ID/Product ID supporting bus is rather unwise. */
+typedef struct {
+       /*!\brief The number of driver classes in the driver_classes array. */
+       int32_t num_driver_classes;
+       /*!\brief An array of declarations of driver classes available to the runtime. 
+        *
+        * This array should not necessarily contain the entire list of EDI classes implemented by the driver.  Instead, it should
+        * contain a list of those classes which the driver has correctly initialized itself to provide instances of with full
+        * functionality. */
+       edi_class_declaration_t *driver_classes;
+       /*!\brief The driver's quota function. */
+       k_quota_t k_quota;
+       /*!\brief The driver's name. */
+       edi_string_t driver_name;
+       /*!\brief The bus of the device this driver wants to drive, if applicable.
+        *
+        * The driver does not have to supply this field, and can also supply "MULTIPLE BUSES" here to indicate that it drives devices
+        * on multiple buses. */
+       edi_string_t driver_bus;
+       /*!\brief The driver's vendor ID, if applicable.
+        *
+        * The driver does not need to supply this field, and should supply -1 to indicate that it does not wish to. */
+       int16_t vendor_id;
+       /*!\brief The driver's device ID, if applicable.
+        *
+        * The driver does not need to supply this field, but can supply it along with vendor_id.  If either vendor_id or this field are
+        * set to -1 the runtime should consider this field not supplied. */
+       int16_t driver_id;
+} edi_initialization_t;        
+/*!\brief A pointer to a driver's initialization function.
+ *
+ * The protocol for the driver's initialization function.  The runtime gives the driver a set of EDI objects representing the
+ * resources it thinks the driver should run with.  This function returns an edi_initialization_t structure containing declarations
+ * of the EDI classes the driver can make available to the runtime after initialization.  If any member of that structure contains 0
+ * or NULL, it is considered invalid and the runtime should destroy the driver without calling its driver_finish() routine. */
+typedef edi_initialization_t (*driver_init_t)(int32_t num_resources,edi_object_metadata_t *resources);
+/*!\brief Requests more resources from the runtime.  Can be called during driver initialization.
+ *
+ * Called to negotiate with the runtime for the right to create further EDI objects/obtain further resources owned by the runtime.
+ * When the driver calls this routine, the runtime decides whether to grant more resources.  If yes, this call returns true, and the
+ * driver can proceed to try and create the objects it desires, in addition to destroying EDI objects it doesn't want.  Otherwise,
+ * it returns false.
+ * The driver must deal with whatever value this routine returns. */
+bool edi_negotiate_resources();
+
+/*! \brief Returns the driver's quota of objects for a given runtime-owned class. 
+ *
+ * This function takes an edi_string_t with the name of a runtime-owned class in it and returns the number of objects of that class
+ * which drivers can construct, -1 for infinity, or -2 for an erroneous class name. */
+int32_t quota(edi_string_t resource_class);
+/*! \brief Sends a string to the operating systems debug output or logging facilities. */
+void edi_debug_write(uint32_t debug_string_length, char *debug_string);
+/*! \brief This call destroys all objects and shuts down the entire EDI environment of the driver. 
+ *
+ * This function shuts down EDI as described in INITIALIZATION AND SHUTDOWN above.  All objects are destroyed, EDI functions can no
+ * longer be successfully called, etc.  This function only succeeds when EDI has already been initialized, so it returns -1 when EDI
+ * hasn't been, 1 on success, or 0 for all other errors. */
+int32_t shutdown_edi(void);
+
+/*!\brief A pointer to the driver's finishing/shutdown function.
+ *
+ * The protocol for the driver's shutting down.  This function should do anything the driver wants done before it dies. */
+typedef void (*driver_finish_t)();
+
+#endif
diff --git a/Modules/Interfaces/EDI/edi/edi_devices.h b/Modules/Interfaces/EDI/edi/edi_devices.h
new file mode 100644 (file)
index 0000000..245e01f
--- /dev/null
@@ -0,0 +1,135 @@
+#ifndef EDI_DEVICES_H
+
+/* Copyright (c)  2006  Eli Gottlieb.
+ * Permission is granted to copy, distribute and/or modify this document
+ * under the terms of the GNU Free Documentation License, Version 1.2
+ * or any later version published by the Free Software Foundation;
+ * with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
+ * Texts.  A copy of the license is included in the file entitled "COPYING". */
+
+/* Edited by thePowersGang (John Hodge) June 2009
+ * - Add #ifdef EDI_MAIN_FILE
+ */
+
+#define EDI_DEVICES_H
+
+/*! \file edi_devices.h
+ * \brief Declaration and description of simple classes for implementation by EDI drivers to represent hardware devices.
+ *
+ * Data structures and algorithms this header represents:
+ *
+ *     DATA STRUCTURE AND ALGORITHM: BASIC DEVICES - There are two functions, select() for waiting on devices and ioctl() for
+ * controlling them, common to many POSIX devices.  Implementations of EDI-CHARACTER-DEVICE or EDI-BLOCK-DEVICE may implement either of
+ * these or both, and users of such objects much query for the methods to see if they're supported.  Obviously, runtime or driver
+ * developers don't *need* to support these.
+ *
+ *     DATA STRUCTURE AND ALGORITHM: CHARACTER DEVICES - The class EDI-CHARACTER-DEVICE provides a very basic interface to character
+ * devices, which read and write streams of characters.  As such, this class only provides read() and write().  The calls attempt a
+ * likeness to POSIX.
+ *
+ *     DATA STRUCTURE AND ALGORITHM: BLOCK DEVICES - The class EDI-BLOCK-DEVICE provides a very basic interface to block devices, which
+ * can read(), write() and seek() to blocks of a specific size in an array of blocks with a specific size.  Its declarations and
+ * semantics should behave like those of most POSIX operating systems.
+ *
+ * Note that EDI runtimes should not implement these classes.  Their declarations are provided for drivers to implement. */
+
+#include "edi_objects.h"
+
+/* Methods common to all EDI device classes specified in this header. */
+
+/*!\brief EAGAIN returned by functions for block and character devices.
+ *
+ * Means that the amount of data the device has ready is less than count. */
+#define EAGAIN -1
+/*!\brief EBADOBJ returned by functions for block and character devices.
+ *
+ * Means that the object passed as the method's this point was not a valid object of the needed class. */
+#define EBADOBJ -2
+/*!\brief EINVAL returned by functions for block and character devices.
+ *
+ * Means that the method got passed invalid parameters. */
+#ifdef EINVAL
+# undef EINVAL
+#endif
+#define EINVAL -3
+
+/*!\brief select() type to wait until device is writable. */
+#define EDI_SELECT_WRITABLE 0
+/*!\brief select() type to wait until device is readable. */
+#define EDI_SELECT_READABLE 1
+
+/*!\brief Argument to seek().  Sets the block offset (ie: the "current block" index) to the given whence value. */
+#define EDI_SEEK_SET 0
+/*!\brief Argument to seek().  Sets the block offset (ie: the "current block" index) to its current value + whence. */
+#define EDI_SEEK_CURRENT 1
+
+#ifdef EDI_MAIN_FILE
+/*!\brief Arguments to EDI's basic select() function. */
+edi_variable_declaration_t select_arguments[2] = {{"pointer void","device",1},
+                                                {"unsigned int32_t","select_type",1}};
+/*!\brief Declaration of EDI's basic select() function. 
+ *
+ * Contrary to the POSIX version, this select() puts its error codes in its return value. */
+edi_function_declaration_t select_declaration = {"int32_t","edi_device_select",0,2,select_arguments,NULL};
+#else
+extern edi_function_declaration_t select_declaration;  // Declare for non main files
+#endif
+
+#ifdef EDI_MAIN_FILE
+/*!\brief Arguments to EDI's basic ioctl() function. */
+edi_variable_declaration_t ioctl_arguments[3] = {{"pointer void","device",1},{"int32_t","request",1},{"pointer void","argp",1}};
+/*!\brief Declaration of EDI's basic ioctl() function. 
+ *
+ * Contrary to the POSIX version, this ioctl() puts its error codes in its return value. */
+edi_function_declaration_t ioctl_declaration = {"int32_t","edi_device_ioctl",0,3,ioctl_arguments,NULL};
+#else
+extern edi_class_declaration_t ioctl_declaration;      // Declare for non main files
+#endif
+
+#ifdef EDI_MAIN_FILE
+/*!\brief Declaration of the arguments EDI-CHARACTER-DEVICE's read() and write() methods. */
+edi_variable_declaration_t chardev_read_write_arguments[3] = {{"pointer void","chardev",1},
+                                                             {"pointer void","buffer",1},
+                                                             {"unsigned int32_t","char_count",1}};
+/*!\brief Declarations of the methods of EDI-CHARACTER-DEVICE, read() and write().
+ *
+ * The code pointers of these function declarations are all given as NULL.  Driver developers implementing EDI-CHARACTER-DEVICE should
+ * fill in these entries with pointers to their own functions. */
+EDI_DEFVAR edi_function_declaration_t chardev_methods[2]= {{"int32_t","edi_chardev_read",0,3,chardev_read_write_arguments,NULL},
+                                               {"int32_t","edi_chardev_write",0,3,chardev_read_write_arguments,NULL}};
+/*!\brief Declaration of the EDI-CHARACTER-DEVICE class.
+ *
+ * Driver developers implementing this class should fill in their own values for constructor, destructor, and possibly even parent
+ * before passing the filled-in structure to the EDI runtime. */
+EDI_DEFVAR edi_class_declaration_t chardev_class = {"EDI-CHARACTER-DEVICE",0,2,chardev_methods,NULL,NULL,NULL};
+#else
+extern edi_class_declaration_t chardev_class;  // Declare for non main files
+#endif
+
+#ifdef EDI_MAIN_FILE
+/*!\brief Arguments to EDI-BLOCK-DEVICE's read() and write() methods. */
+edi_variable_declaration_t blockdev_read_write_arguments[3] = {{"pointer void","blockdev",1},
+                                                              {"pointer void","buffer",1},
+                                                              {"unsigned int32_t","blocks",1}};
+/*!\brief Arguments to EDI-BLOCK-DEVICE's seek() method. */
+edi_variable_declaration_t blockdev_seek_arguments[3] = {{"pointer void","blockdev",1},
+                                                        {"int32_t","offset",1},
+                                                        {"int32_t","whence",1}};
+/*!\brief Declaration of the methods of EDI-BLOCK-DEVICE, read(), write(), seek(), and get_block_size(). 
+ *
+ * The code pointers of these function declarations are all given as NULL.  Driver developers implementing EDI-BLOCK-DEVICE should fill
+ * these entries in with pointers to their own functions. */
+edi_function_declaration_t blockdev_methods[4] = {{"int32_t","edi_blockdev_read",0,3,blockdev_read_write_arguments,NULL},
+                                                 {"int32_t","edi_blockdev_write",0,3,blockdev_read_write_arguments,NULL},
+                                                 {"int32_t","edi_blockdev_seek",0,3,blockdev_seek_arguments,NULL},
+                                                 {"unsigned int32_t","edi_blockdev_get_block_size",0,0,NULL,NULL}};
+/*!\brief Declaration of the EDI-BLOCK-DEVICE class.
+ *
+ * Driver developers implementing this class should fill in their own values for constructor, destructor, and possibly even parent
+ * before passing the filled-in structure to the EDI runtime. */
+edi_class_declaration_t blockdev_class = {"EDI-BLOCK-DEVICE",0,4,blockdev_methods,NULL,NULL,NULL};
+#else
+extern edi_class_declaration_t blockdev_class; // Declare for non main files
+#endif
+
+#endif
diff --git a/Modules/Interfaces/EDI/edi/edi_dma_streams.h b/Modules/Interfaces/EDI/edi/edi_dma_streams.h
new file mode 100644 (file)
index 0000000..8ab80cc
--- /dev/null
@@ -0,0 +1,52 @@
+#ifndef EDI_DMA_STREAMS_H
+
+/* Copyright (c)  2006  Eli Gottlieb.
+ * Permission is granted to copy, distribute and/or modify this document
+ * under the terms of the GNU Free Documentation License, Version 1.2
+ * or any later version published by the Free Software Foundation;
+ * with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
+ * Texts.  A copy of the license is included in the file entitled "COPYING". */
+
+#define EDI_DMA_STREAMS_H
+
+/*! \file edi_dma_streams.h 
+ * \brief EDI's stream subclass for handling Direct Memory Access hardware.
+ *
+ * Data structures and algorithms this header represents:
+ *
+ *     DATA STRUCTURE: DMA STREAMS - DMA streams are objects of the class EDI-STREAM-DMA used to pass data between a buffer of
+ * memory and the computer's DMA hardware.  It is the responsibility of the object to allocate memory for its stream memory buffer
+ * which can be used with DMA hardware and to program the DMA hardware for transmissions.  DMA streams can be bidirectional if the
+ * correct DMA mode is used. */
+
+#include "edi_objects.h"
+
+#define DMA_STREAM_CLASS       "EDI-STREAM-DMA"
+
+/*! \brief The name of the EDI DMA stream class.
+ *
+ * An edi_string_t with the class name "EDI-STREAM-DMA" in it. */
+#if defined(EDI_MAIN_FILE) || defined(IMPLEMENTING_EDI)
+const edi_string_t dma_stream_class = DMA_STREAM_CLASS;
+#else
+extern const edi_string_t dma_stream_class;
+#endif
+
+#ifndef IMPLEMENTING_EDI
+/*! \brief int32_t EDI-STREAM-DMA.init_dma_stream(unsigned int32_t channel,unsigned int32_t mode,unsigned int32_t buffer_pages);
+ *
+ * Pointer to the init_dma_stream() method of class EDI-STREAM-DMA, which initializes a DMA stream with a DMA channel, DMA mode, and
+ * the number of DMA-accessible memory pages to keep as a buffer.  It will only work once per stream object.  It's possible return
+ * values are 1 for sucess, -1 for invalid DMA channel, -2 for invalid DMA mode, -3 for inability to allocate enough buffer pages and
+ * 0 for all other errors. */
+EDI_DEFVAR  int32_t (*init_dma_stream)(object_pointer stream, uint32_t channel, uint32_t mode, uint32_t buffer_pages);
+/*! \brief int32_t EDI-STREAM-DMA.transmit(data_pointer *anchor,unsigned int32 num_bytes,bool sending);
+ *
+ * Pointer to the dma_stream_transmit() method of class EDI-STREAM-DMA, which transmits the given number of bytes of data through
+ * the DMA stream to/from the given anchor (either source or destination), in the given direction.  It returns 1 on success, -1 on
+ * an uninitialized or invalid DMA stream object, -2 when the anchor was NULL or otherwise invalid, -3 if the DMA stream can't
+ * transmit in the given direction, and 0 for all other errors. */
+EDI_DEFVAR int32_t (*dma_stream_transmit)(object_pointer stream, data_pointer anchor, uint32_t num_bytes, bool sending);
+#endif
+
+#endif
diff --git a/Modules/Interfaces/EDI/edi/edi_interrupts.h b/Modules/Interfaces/EDI/edi/edi_interrupts.h
new file mode 100644 (file)
index 0000000..ef2ffc9
--- /dev/null
@@ -0,0 +1,65 @@
+#ifndef EDI_INTERRUPTS_H
+
+/* Copyright (c)  2006  Eli Gottlieb.
+ * Permission is granted to copy, distribute and/or modify this document
+ * under the terms of the GNU Free Documentation License, Version 1.2
+ * or any later version published by the Free Software Foundation;
+ * with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
+ * Texts.  A copy of the license is included in the file entitled "COPYING". */
+
+#define EDI_INTERRUPTS_H
+
+/*! \file edi_interrupts.h
+ * \brief Declaration and description of EDI's interrupt handling class.
+ *
+ * Data structures and algorithms this header represents:
+ *     DATA STRUCTURE AND ALGORITHM: INTERRUPT OBJECTS - The class EDI-INTERRUPT encapsulates the handling of machine interrupts.
+ * It is initialized with an interrupt number to handle and a handler routine to call when that interrupt occurs.  Only a couple of
+ * guarantees are made to the driver regarding the runtime's implementation of interrupt handling: 1) That the driver's handler is
+ * called for every time the interrupt associated with a valid and initialized interrupt object occurs, in the order of the
+ * occurences, 2) That the runtime handle the architecture-specific (general to the entire machine, not just this device)
+ * end-of-interrupt code when the driver is called without first returning from the machine interrupt.  Note that the runtime hands
+ * out interrupt numbers at its own discretion and policy. */
+
+#include "edi_objects.h"
+
+/*! \brief Macro constant containing the name of the interrupt class
+ */
+#define INTERRUPTS_CLASS       "EDI-INTERRUPT"
+/*! \brief The name of EDI's interrupt-handling class.
+ *
+ * An edi_string_t holding the name of the runtime-implemented interrupt object class.  It's value is "EDI-INTERRUPT". */
+#if defined(EDI_MAIN_FILE) || defined(IMPLEMENTING_EDI)
+const edi_string_t interrupts_class = INTERRUPTS_CLASS;
+#else
+extern const edi_string_t interrupts_class;
+#endif
+
+/*! \brief A pointer to an interrupt handling function.
+ *
+ * A pointer to a function called to handle interrupts.  Its unsigned int32_t parameter is the interrupt number that is being
+ * handled. */
+typedef void (*interrupt_handler_t)(uint32_t interrupt_number);
+
+#ifndef IMPLEMENTING_EDI
+/*! \brief Initializes an interrupt object with an interrupt number and a pointer to a handler function.
+ *
+ * A pointer to the init_interrupt() method of class EDI-INTERRUPT.  This method initializes a newly-created interrupt object with an
+ * interrupt number and a pointer to the driver's handler of type interrupt_handler_t.  It can only be called once per object, and
+ * returns 1 on success, fails with -1 when the interrupt number is invalid or unacceptable to the runtime, fails with -2 when the
+ * pointer to the driver's interrupt handler is invalid, and fails with -3 for all other errors. */
+EDI_DEFVAR int32_t (*init_interrupt)(object_pointer interrupt, uint32_t interrupt_number, interrupt_handler_t handler);
+/*! \brief Get this interrupt object's interrupt number. */
+EDI_DEFVAR uint32_t (*interrupt_get_irq)(object_pointer interrupt);
+/*! \brief Set a new handler for this interrupt object. */
+EDI_DEFVAR void (*interrupt_set_handler)(object_pointer interrupt, interrupt_handler_t handler);
+/*! \brief Return from this interrupt, letting the runtime run any necessary End-Of-Interrupt code.
+ *
+ * A pointer to the interrupt_return() method of class EDI-INTERRUPT.  This method returns from the interrupt designated by the
+ * calling interrupt object.  If there is a machine-wide end-of-interrupt procedure and the driver was called during the handling of
+ * the machine interrupt (as opposed to delaying the handling and letting the runtime EOI), the runtime runs it during this method.
+ * This method has no return value, since once it's called control leaves the calling thread. */
+EDI_DEFVAR void (*interrupt_return)(object_pointer interrupt);
+#endif
+
+#endif
diff --git a/Modules/Interfaces/EDI/edi/edi_memory_mapping.h b/Modules/Interfaces/EDI/edi/edi_memory_mapping.h
new file mode 100644 (file)
index 0000000..ba8dff3
--- /dev/null
@@ -0,0 +1,86 @@
+#ifndef EDI_MEMORY_MAPPING_H
+
+/* Copyright (c)  2006  Eli Gottlieb.
+ * Permission is granted to copy, distribute and/or modify this document
+ * under the terms of the GNU Free Documentation License, Version 1.2
+ * or any later version published by the Free Software Foundation;
+ * with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
+ * Texts.  A copy of the license is included in the file entitled "COPYING". */
+
+#define EDI_MEMORY_MAPPING_H
+
+/*! \file edi_memory_mapping.h
+ * \brief Declaration and description of EDI's class for mapping physical pages into the driver's address space.
+ *
+ * Data structures and algorithms this header represents:
+ *     ALGORITHM: MEMORY MAPPINGS - Memory mapping objects of the class EDI-MEMORY-MAPPING are used to give virtual (driver-visible)
+ * addresses to sections of physical memory.  These can either be memory mappings belonging to hardware devices or plain RAM which
+ * the driver wants page-aligned.  A memory mapping object is initialized with the physical address for the memory mapping and the
+ * number of pages the mapping takes up, or simply the desired length of the a physically contiguous buffer in pages.  The class's
+ * two methods map the section of memory into and out of the driver's virtual address space. */
+
+#include "edi_objects.h"
+
+/*! \brief The name of EDI's memory mapping class.
+ *
+ * An edi_string_t with the name of the memory mapping class, "EDI-MEMORY-MAPPING". */
+#if defined(EDI_MAIN_FILE) || defined(IMPLEMENTING_EDI)
+const edi_string_t memory_mapping_class = "EDI-MEMORY-MAPPING";
+#else
+extern const edi_string_t memory_mapping_class;
+#endif
+
+/*! \brief Flag representing Strong Uncacheable caching method. */
+#define CACHING_STRONG_UNCACHEABLE 0
+/*! \brief Flag representing Uncacheable caching method. */
+#define CACHING_UNCACHEABLE 1
+/*! \brief Flag representing Write combining caching method. */
+#define CACHING_WRITE_COMBINING 2
+/*! \brief Flag representing Write Through caching method. */
+#define CACHING_WRITE_THROUGH 3
+/*! \brief Flag representing Write Back caching method. */
+#define CACHING_WRITE_BACK 3
+/*! \brief Flag representing Write Protected caching method. */
+#define CACHING_WRITE_PROTECTED 3
+
+#ifndef IMPLEMENTING_EDI
+/*! \brief Initialize an EDI-MEMORY-MAPPING object with a physical address range.
+ *
+ * This method takes the start_physical_address of a memory mapping and the number of pages in that mapping and uses these arguments
+ * to initialize an EDI-MEMORY-MAPPING object.  It can only be called once per object.  It returns 1 when successful, -1 when an
+ * invalid physical address is given (one that the runtime knows is neither a physical memory mapping belonging to a device nor
+ * normal RAM), -2 when the number of pages requested is bad (for the same reasons as the starting address can be bad), and 0 for
+ * all other errors. 
+ *
+ * Note that this method can't be invoked on an object which has already initialized via init_memory_mapping_with_pages(). */
+EDI_DEFVAR int32_t (*init_memory_mapping_with_address)(object_pointer mapping, data_pointer start_physical_address, uint32_t pages);
+/*! \brief Initialize an EDI-MEMORY-MAPPING object by requesting a number of new physical pages.
+ *
+ * This method takes a desired number of physical pages for a memory mapping, and uses that number to initialize an
+ * EDI-MEMORY-MAPPING object by creating a buffer of contiguous physical pages.  It can only be called once per object.  It returns
+ * 1 when successful, -1 when the request for pages cannot be fulfilled, and 0 for all other errors.
+ *
+ * Note that this method cannot be called if init_memory_mapping_with_address() has already been used on the given object. */
+EDI_DEFVAR int32_t (*init_memory_mapping_with_pages)(object_pointer mapping, uint32_t pages);
+/*! \brief Map the memory-mapping into this driver's visible address space.
+ *
+ * This asks the runtime to map a given memory mapping into the driver's virtual address space.  Its parameter is the address of a
+ * data_pointer to place the virtual address of the mapping into.  This method returns 1 on success, -1 on an invalid argument, -2
+ * for an uninitialized object, and 0 for all other errors. */
+EDI_DEFVAR int32_t (*map_in_mapping)(object_pointer mapping, data_pointer *address_mapped_to);
+/*! \brief Unmap the memory mapping from this driver's visible address space.
+ *
+ * This method tries to map the given memory mapping out of the driver's virtual address space.  It returns 1 for success, -1
+ * for an uninitialized memory mapping object, -2 if the mapping isn't mapped into the driver's address space already, and 0
+ * for all other errors. */
+EDI_DEFVAR int32_t (*map_out_mapping)(object_pointer mapping);
+
+/*! \brief Set the caching flags for a memory mapping. */
+EDI_DEFVAR void (*mapping_set_caching_method)(object_pointer mapping, uint32_t caching_method);
+/*! \brief Get the current caching method for a memory mapping. */
+EDI_DEFVAR uint32_t (*mapping_get_caching_method)(object_pointer mapping);
+/*! \brief Flush write-combining buffers on CPU to make sure changes to memory mapping actually get written.  Only applies to a Write Combining caching method (I think.).*/
+EDI_DEFVAR void (*flush_write_combining_mapping)(object_pointer mapping);
+#endif
+
+#endif
diff --git a/Modules/Interfaces/EDI/edi/edi_objects.h b/Modules/Interfaces/EDI/edi/edi_objects.h
new file mode 100644 (file)
index 0000000..0e47951
--- /dev/null
@@ -0,0 +1,257 @@
+#ifndef EDI_OBJECTS_H
+
+/* Copyright (c)  2006  Eli Gottlieb.
+ * Permission is granted to copy, distribute and/or modify this document
+ * under the terms of the GNU Free Documentation License, Version 1.2
+ * or any later version published by the Free Software Foundation;
+ * with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
+ * Texts.  A copy of the license is included in the file entitled "COPYING". */
+
+#define EDI_OBJECTS_H
+
+/*! \file edi_objects.h
+ * \brief The header file for basic EDI types and the object system.
+ *
+ * This file contains declarations of EDI's primitive data types, as well as structures and functions for with the object system.
+ * It represents these data structures and algorithms:
+ * 
+ *     DATA STRUCTURE: THE CLASS LIST - EDI implementing runtime's must keep an internal list of classes implemented by the runtime
+ *     and separate lists of classes implemented by each driver.  Whoever implements a class is said to "own" that class.  The
+ *     internal format of this list is up to the runtime coders, but it must be possible to recreate the original list of
+ *     edi_class_declaration structures the driver declared to the runtime from it.  This list is declared to the runtime in an
+ *     initialization function in the header edi.h.  The object_class member of an edi_object_metadata structure must point to that
+ *     object's class's entry in this list.
+ *     
+ *     ALGORITHM AND DATA STRUCTURE: CLASSES AND INHERITANCE - Classes are described using edi_class_declaration_t structures and
+ *     follow very simple rules.  All data is private and EDI provides no way to access instance data, so there are no member
+ *     variable declarations.  However, if the data isn't memory-protected (for example, driver data on the driver heap) EDI allows
+ *     the possibility of pointer access to data, since runtime and driver coders could make use of that behavior.  Classes may have
+ *     one ancestor by declaring so in their class declaration structure, and if child methods are different then parent methods
+ *     the children always override their parents.  An EDI runtime must also be able to check the existence and ownership of a given
+ *     class given its name in an edi_string_t.
+ *     
+ *     ALGORITHM: OBJECT CREATION AND DESTRUCTION - An EDI runtime should be able to call the constructor of a named class, put the
+ *     resulting object_pointer into an edi_object_metadata_t and return that structure.  The runtime should also be able to call an
+ *     object's class's destructor when given a pointer to a valid edi_metadata_t for an already-existing object.  Data equivalent
+ *     to an edi_object_metadata_t should also be tracked by the runtime for every object in existence in case of sudden EDI shutdown
+ *     (see edi.h).
+ *
+ *     ALGORITHM: RUNTIME TYPE INFORMATION - When passed the data_pointer member of an edi_object_metadata_t to a valid object, an
+ *     EDI runtime must be able to return an edi_string_t containing the name of that object's class and to return function_pointers
+ *     to methods when the required information to find the correct method is given by calling a class's method getting function.*/
+
+/* If the EDI headers are linked with the standard C library, they use its type definitions.  Otherwise, equivalent definitions are
+ * made.*/
+#if __STDC_VERSION__ == 199901L
+# include <stdbool.h>
+# include <stdint.h>
+#else
+# ifndef NULL
+#  define      NULL    ((void*)0)
+# endif
+typedef unsigned char bool;
+# define true 1
+# define false 0
+typedef char int8_t;
+typedef short int16_t;
+typedef long int32_t;
+typedef long long int64_t;
+typedef unsigned char  uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned long  uint32_t;
+typedef unsigned long long     uint64_t;
+#endif
+
+/*! \brief Define a variable in the header
+ */
+#ifdef EDI_MAIN_FILE
+# define EDI_DEFVAR
+#else
+# define EDI_DEFVAR    extern
+#endif
+
+/*! \brief A pointer to the in-memory instance of an object.
+ *
+ * This type is sized just like a general C pointer type (whatever*) for the target architecture.  It's passed as a first parameter
+ * to all methods, thus allowing EDI classes to be implemented as C++ classes and providing some protection from confusing objects
+ * with normal pointers.  Equivalent to a C++ this pointer or an Object Pascal Self argument. */
+typedef void *object_pointer;
+/*! \brief A basic pointer type pointing to arbitrary data in an arbitrary location. */
+typedef void *data_pointer;
+/*! \brief A basic function pointer type.
+ *
+ * A pointer to a piece of code which can be called and return to its caller, used to distinguish between pointers to code and
+ * pointers to data.  Its size is hardware-dependent. */
+typedef void (*function_pointer)(void);
+/*! \brief The length of an EDI string without its null character. */
+#define EDI_STRING_LENGTH 31
+/*! \brief A type representing a 31-character long string with a terminating NULL character at the end.  All of EDI uses this type
+ * for strings.
+ *
+ * A null-terminated string type which stores characters in int8s.  It allows for 31 characters in each string, with the final
+ * character being the NULL terminator.  Functions which use this type must check that its final character is NULL, a string which
+ * doesn't not have this property is invalid and insecure.  I (the author of EDI) know and understand that this form of a string
+ * suffers from C programmer's disease, but I can't use anything else without either making string use far buggier or dragging
+ * everyone onto a better language than C.  */
+typedef int8_t edi_string_t[0x20];
+/*! \brief A type representing a pointer form of #edi_string_t suitable for function returns
+ */
+typedef int8_t *edi_string_ptr_t;
+
+/*! \var EDI_BASE_TYPES
+ * \brief A constant array of edi_string_t's holding every available EDI primitive type. */
+/*! \var EDI_TYPE_MODIFIERS
+ * \brief A constant array of edi_string_t's holding available modifiers for EDI primitive types. */
+#ifdef IMPLEMENTING_EDI
+ const edi_string_t EDI_BASE_TYPES[9] = {"void","bool","int8_t","int16_t","int32_t","int64_t","function_pointer","intreg","edi_string_t"};
+ const edi_string_t EDI_TYPE_MODIFIERS[2] = {"pointer","unsigned"};
+#else
+ //extern const edi_string_t EDI_BASE_TYPES[9] = {"void","bool","int8_t","int16_t","int32_t","int64_t","function_pointer","intreg", "edi_string_t"};
+ //extern const edi_string_t EDI_TYPE_MODIFIERS[2] = {"pointer","unsigned"};
+ extern const edi_string_t EDI_BASE_TYPES[9];
+ extern const edi_string_t EDI_TYPE_MODIFIERS[2];
+#endif
+
+/*! \struct edi_object_metadata_t
+ * \brief A packed structure holding all data to identify an object to the EDI object system. */
+typedef struct {
+       /*! \brief Points to the instance data of the object represented by this structure.
+        *
+        * An object_pointer to the object this structure refers to.  The this pointer, so to speak. */
+       object_pointer object;
+       /*! \brief Points the internal record kept by the runtime describing the object's class.
+        *
+        * Points to wherever the runtime has stored the class data this object was built from.  The class data doesn't need to be
+        * readable to the driver, and so this pointer can point to an arbitrary runtime-reachable location. */
+       data_pointer object_class;
+} edi_object_metadata_t;
+
+/*! \struct edi_variable_declaration_t
+ * \brief The data structure used to describe a variable declaration to the EDI object system.
+ *
+ * The data structure used to describe a variable declaration to the EDI object system.  The context of the declaration depends on
+ * where the data structure appears, ie: alone, in a class declaration, in a parameter list, etc. */
+typedef struct {
+       /*! \brief The type of the declared variable. 
+        *
+        * The type of the variable, which must be a valid EDI primitive type as specified in the constant EDI_BASE_TYPES and
+        * possibly modified by a modifier specified in the constant EDI_TYPE_MODIFIERS. */
+       edi_string_t type;
+       /*! \brief The name of the declared variable. */
+       edi_string_t name;
+       /*! \brief Number of array entries if this variable is an array declaration. 
+        *
+        * An int32_t specifying the number of variables of 'type' in the array 'name'.  For a single variable this value should
+        * simply be set to 1, for values greater than 1 a packed array of contiguous variables is being declared, and a value of 0
+        * is invalid. */
+       int32_t array_length;
+} edi_variable_declaration_t;
+
+/*! \struct edi_function_declaration_t
+ * \brief The data structure used to declare a function to the EDI object system. */
+typedef struct {
+       /*! \brief The return type of the function.  The same type rules which govern variable definitions apply here. */
+       edi_string_t return_type;
+       /*! \brief The name of the declared function. */
+       edi_string_t name;
+       /*! \brief The version number of the function, used to tell different implementations of the same function apart. */
+       uint32_t version;
+       /*! \brief The number of arguments passed to the function.
+        *
+        * The number of entries in the member arguments that the object system should care about.  Caring about less misses
+        * parameters to functions, caring about more results in buffer overflows. */
+       uint32_t num_arguments;
+       /*! \brief An array of the declared function's arguments.
+        *
+        * A pointer to an array num_arguments long containing edi_variable_declaration_t's for each argument to the declared
+        * function.*/
+       edi_variable_declaration_t *arguments;
+       /*!\brief A pointer to the declared function's code in memory. */
+       function_pointer code;
+} edi_function_declaration_t;
+
+/*! \brief A pointer to a function for constructing instances of a class.
+ *
+ * A pointer to a function which takes no parameters and returns an object_pointer pointing to the newly made instance of a class.
+ * It is the constructor's responsibility to allocate memory for the new object.  Each EDI class needs one of these. */
+typedef object_pointer (*edi_constructor_t)(void);
+/*! \brief A pointer to a function for destroying instances of a class.
+ *
+ * A pointer to a function which takes an object_pointer as a parameter and returns void.  This is the destructor counterpart to a
+ * class's edi_constructor_t, it destroys the object pointed to by its parameter and frees the object's memory.  Every class must
+ * have one */
+typedef void (*edi_destructor_t)(object_pointer);
+
+/*! \brief Information the driver must give the runtime about its classes so EDI can construct them and call their methods.
+ *
+ * A structure used to declare a class to an EDI runtime so instances of it can be constructed by the EDI object system. */
+typedef struct {
+       /*! \brief The name of the class declared by the structure. */
+       edi_string_t name;
+       /*! \brief The version of the class.  This number is used to tell identically named but differently
+        * implemented classes apart.*/
+       uint32_t version;
+       /*! \brief The number of methods in the 'methods' function declaration array. */
+       uint32_t num_methods;
+       /*! \brief An array of edi_function_declaration_t declaring the methods of this class. */
+       edi_function_declaration_t *methods;
+       /*! \brief Allocates the memory for a new object of the declared class and constructs the object.  Absolutely required.*/
+       edi_constructor_t constructor;
+       /*! \brief Destroys the given object of the declared class and frees its memory. Absolutely required. */
+       edi_destructor_t destructor;
+       /*! \brief A pointer to another EDI class declaration structure specifying the declared class's parent class. 
+        *
+        * Points to a parent class declared in another class declaration.  It can be NULL to mean this class has no parent. */
+       struct edi_class_declaration_t *parent;
+} edi_class_declaration_t;
+
+/*! \brief Checks the existence of the named class.
+ *
+ * This checks for the existence on THE CLASS LIST of the class named by its edi_string_t parameter and returns a signed int32_t.  If
+ * the class isn't found (ie: it doesn't exist as far as EDI is concerned) -1 is returned, if the class is owned by the driver
+ * (implemented by the driver and declared to the runtime by the driver) 0, and if the class is owned by the runtime (implemented by
+ * the runtime) 1. */
+int32_t check_class_existence(edi_string_t class_name);
+/*! \brief Constructs an object of the named class and returns its object_pointer and a data_pointer to its class data.
+ *
+ * Given a valid class name in an edi_string_t this function constructs the specified class and returns an edi_metadata_t describing
+ * the new object as detailed in OBJECT CREATION AND DESTRUCTION.  If the construction fails it returns a structure full of NULL
+ * pointers. */
+edi_object_metadata_t construct_object(edi_string_t class_name);
+/*! \brief Destroys the given object using its class data.
+ *
+ * As specified in OBJECT CREATION AND DESTRUCTION this function should destroy an object when given its valid edi_metadata_t.  The
+ * destruction is accomplished by calling the class's destructor. */
+void destroy_object(edi_object_metadata_t object);
+/*! \brief Obtains a function pointer to a named method of a given class. 
+ *
+ * When given a valid data_pointer object_class from an edi_object_metadata_t and an edi_string_t representing the name of the
+ * desired method retrieves a function_pointer to the method's machine code in memory.  If the desired method isn't found, NULL is
+ * returned. */
+function_pointer get_method_by_name(data_pointer object_class,edi_string_t method_name);
+/*! \brief Obtains a function pointer to a method given by a declaration of the given class if the class's method matches the
+ * declaration. 
+ *
+ * Works just like get_method_by_name(), but by giving an edi_function_declaration_t for the desired method instead of just its name.
+ * Performs detailed checking against THE CLASS LIST to make sure that the method returned exactly matches the declaration passed
+ * in. */
+function_pointer get_method_by_declaration(data_pointer object_class,edi_function_declaration_t declaration);
+
+/* Runtime typing information. */
+/*! \brief Returns the name of the class specified by a pointer to class data. 
+ *
+ * Given the data_pointer to an object's class data as stored in an edi_object_metadata_t retrieves the name of the object's class
+ * and returns it in an edi_string_t. */
+edi_string_ptr_t get_object_class(data_pointer object_class);
+/*! \brief Returns the name of a class's parent class.
+ *
+ * When given an edi_string_t with a class name in it, returns another edi_string_t containing the name of the class's parent, or an
+ * empty string. */
+edi_string_ptr_t get_class_parent(edi_string_t some_class);
+/*! \brief Returns the internal class data of a named class (if it exists) or NULL.
+ *
+ * When given an edi_string_t with a valid class name in it, returns a pointer to the runtime's internal class data for that class.
+ * Otherwise, it returns NULL. */
+data_pointer get_internal_class(edi_string_t some_class);
+
+#endif 
diff --git a/Modules/Interfaces/EDI/edi/edi_port_io.h b/Modules/Interfaces/EDI/edi/edi_port_io.h
new file mode 100644 (file)
index 0000000..a2a1773
--- /dev/null
@@ -0,0 +1,90 @@
+#ifndef EDI_PORT_IO_H
+
+/* Copyright (c)  2006  Eli Gottlieb.
+ * Permission is granted to copy, distribute and/or modify this document
+ * under the terms of the GNU Free Documentation License, Version 1.2
+ * or any later version published by the Free Software Foundation;
+ * with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
+ * Texts.  A copy of the license is included in the file entitled "COPYING". */
+
+/* Modified by thePowersGang (John Hodge)
+ * - Surround variable definitions with an #ifdef IMPLEMENTING_EDI
+ */
+
+#define EDI_PORT_IO_H
+
+/*! \file edi_port_io.h
+ * \brief Declaration and description of EDI's port I/O class.
+ *
+ * Data structures and algorithms this header represents:
+ *
+ *     DATA STRUCTURE AND ALGORITHM: PORT I/O OBJECTS - A class named "EDI-IO-PORT" is defined as an encapsulation of the port I/O
+ * used on some machine architectures.  Each object of this class represents a single I/O port which can be read from and written to
+ * in various sizes.  Each port can be held by one object only at a time. */
+
+#include "edi_objects.h"
+
+/*! \brief Macro to create methods for reading from ports.
+ *
+ * This macro creates four similar methods, differing in the size of the type they read from the I/O port held by the object.  Their
+ * parameter is a pointer to the output type, which is filled with the value read from the I/O port.  They return 1 for success, -1
+ * for an uninitialized I/O port object, and 0 for other errors. */
+#define port_read_method(type,name) int32_t (*name)(object_pointer port_object, type *out)
+/*! \brief Macro to create methods for writing to ports.
+ *
+ * This macro creates four more similar methods, differing in the size of the type they write to the I/O port held by the object.
+ * Their parameter is the value to write to the port.  They return 1 for success, -1 for an uninitialized I/O port object and 0 for
+ * other errors. */
+#define port_write_method(type,name) int32_t (*name)(object_pointer port_object, type in)
+
+/*! \brief Name of EDI I/O port class. (Constant)
+ *
+ * A CPP constant with the value of #io_port_class */
+#define        IO_PORT_CLASS   "EDI-IO-PORT"
+/*! \brief Name of EDI I/O port class.
+ *
+ * An edi_string_t containing the class name "EDI-IO-PORT". */
+#if defined(EDI_MAIN_FILE) || defined(IMPLEMENTING_EDI)
+const edi_string_t io_port_class = IO_PORT_CLASS;
+#else
+extern const edi_string_t io_port_class;
+#endif
+
+#ifndef IMPLEMENTING_EDI
+/*! \brief int32_t EDI-IO-PORT.init_io_port(unsigned int16_t port);
+ *
+ * This method takes an unsigned int16_t representing a particular I/O port and initializes the invoked EDI-IO-PORT object with it.
+ * The method returns 1 if successful, -1 if the I/O port could not be obtained for the object, and 0 for all other errors. */
+EDI_DEFVAR int32_t (*init_io_port)(object_pointer port_object, uint16_t port);
+/*! \brief Get the port number from a port object. */
+EDI_DEFVAR uint16_t (*get_port_number)(object_pointer port);
+/*! \brief Method created by port_read_method() in order to read bytes (int8s) from I/O ports. */
+EDI_DEFVAR int32_t (*read_byte_io_port)(object_pointer port_object, int8_t *out);
+/*! \brief Method created by port_read_method() in order to read words (int16s) from I/O ports. */
+EDI_DEFVAR int32_t (*read_word_io_port)(object_pointer port_object, int16_t *out);
+/*! \brief Method created by port_read_method() in order to read longwords (int32s) from I/O ports. */
+EDI_DEFVAR int32_t (*read_long_io_port)(object_pointer port_object, int32_t *out);
+/*! \brief Method created by port_read_method() in order to read long longwords (int64s) from I/O ports. */
+EDI_DEFVAR int32_t (*read_longlong_io_port)(object_pointer port_object,int64_t *out);
+/*! \brief Method of EDI-IO-PORT to read long strings of data from I/O ports.
+ *
+ * Reads arbitrarily long strings of data from the given I/O port.  Returns 1 for success, -1 for an uninitialized port object, -2
+ * for a bad pointer to the destination buffer, and 0 for all other errors. */
+EDI_DEFVAR int32_t (*read_string_io_port)(object_pointer port_object, uint32_t data_length, uint8_t *out);
+/*! \brief Method created by port_write_method() in order to write bytes (int8s) to I/O ports. */
+EDI_DEFVAR int32_t (*write_byte_io_port)(object_pointer port_object, int8_t in);
+/*! \brief Method created by port_write_method() in order to write words (int16s) to I/O ports. */
+EDI_DEFVAR int32_t (*write_word_io_port)(object_pointer port_object, int16_t in);
+/*! \brief Method created by port_write_method() in order to write longwords (int32s) to I/O ports. */
+EDI_DEFVAR int32_t (*write_long_io_port)(object_pointer port_object, int32_t in);
+/*! \brief Method created by port_write_method() in order to write long longwords (int64s) to I/O ports. */
+EDI_DEFVAR int32_t (*write_longlong_io_port)(object_pointer port_object, int64_t in);
+/*! \brief Method of EDI-IO-PORT to write long strings of data to I/O ports.
+ *
+ * Writes arbitrarily long strings of data to the given I/O port.  Returns 1 for success, -1 for an uninitialized port object, -2
+ * for a bad pointer to the source buffer, and 0 for all other errors. */
+EDI_DEFVAR int32_t (*write_string_io_port)(object_pointer port_object, uint32_t data_length, uint8_t *in);
+
+#endif // defined(IMPLEMENTING_EDI)
+
+#endif
diff --git a/Modules/Interfaces/EDI/edi/edi_pthreads.h b/Modules/Interfaces/EDI/edi/edi_pthreads.h
new file mode 100644 (file)
index 0000000..c21fa75
--- /dev/null
@@ -0,0 +1,175 @@
+#ifndef EDI_PTHREADS
+
+/* Copyright (c)  2006  Eli Gottlieb.
+ * Permission is granted to copy, distribute and/or modify this document
+ * under the terms of the GNU Free Documentation License, Version 1.2
+ * or any later version published by the Free Software Foundation;
+ * with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
+ * Texts.  A copy of the license is included in the file entitled "COPYING". */
+
+#define EDI_PTHREADS
+/*!\file edi_pthreads.h
+ * \brief A basic subset of POSIX Threads functionality, providing threading and thread synchronization.
+ *
+ * A very basic POSIX Threads interface.  Note that pthreads are not a class, because none of these calls really gels with
+ * object-oriented programming.  Also, if drivers aren't processes or threads under the implementing operating system a small
+ * threading system must be implemented in-runtime just to multiplex the pthreads of EDI drivers.  Sorry about that.
+ *
+ * Data structures and algorithms this header represents:
+ *
+ *     ALGORITHM AND DATA STRUCTURE: POSIX Threading - The runtime must provide enough of a POSIX threading interface to implement
+ * the calls described here.  The actual multithreading must be performed by the runtime, and the runtime can implement that
+ * multithreading however it likes as long as the given POSIX Threads subset works.  There is, however, a caveat: since the runtime
+ * calls the driver like it would a library, the driver must perceive all calls made to it by the runtime as running under one thread.
+ * From this thread the driver can create others.  Such behavior is a quirk of EDI, and does not come from the POSIX standard.
+ * However, it is necessary to provide the driver with a thread for its own main codepaths.  For further details on a given POSIX
+ * Threading routine, consult its Unix manual page. */
+
+#include "edi_objects.h"
+
+/* Placeholder type definitions.  Users of the PThreads interface only ever need to define pointers to these types. */
+/*!\brief Opaque POSIX Threading thread attribute type. */
+typedef void pthread_attr_t;
+/*!\brief Opaque POSIX Threading mutex (mutual exclusion semaphore) type. */
+typedef void pthread_mutex_t;
+/*!\brief Opaque POSIX Threading mutex attribute type. */
+typedef void pthread_mutex_attr_t;
+
+/*!\struct sched_param
+ * \brief POSIX Threading scheduler parameters for a thread. */
+typedef struct {
+       /*!\brief The priority of the thread. */
+       int32_t sched_priority;
+} sched_param;
+
+/*!\brief POSIX Threading thread identifier. */
+typedef uint32_t pthread_t;
+/*!\brief POSIX Threading thread function type.
+ *
+ * A function pointer to a thread function, with the required signature of a thread function.  A thread function takes one untyped
+ * pointer as an argument and returns an untyped pointer.  Such a function is a thread's main routine: it's started with the thread,
+ * and the thread exits if it returns. */
+typedef void *(*pthread_function_t)(void*);
+
+/*!\brief Insufficient resources. */
+#define EAGAIN -1
+/*!\brief Invalid parameter. */
+#define EINVAL -2
+/*!\brief Permission denied. */
+#define EPERM -3
+/*!\brief Operation not supported. */
+#define ENOTSUP -4
+/*!\brief Priority scheduling for POSIX/multiple schedulers is not implemented. */
+#define ENOSYS -5
+/*!\brief Out of memory. */
+#define ENOMEM -6
+/*!\brief Deadlock.  Crap. */
+#define EDEADLK -7
+/*!\brief Busy.  Mutex already locked. */
+#define EBUSY -8
+
+/*!\brief Scheduling policy for regular, non-realtime scheduling.  The default. */
+#define SCHED_OTHER 0
+/*!\brief Real-time, first-in first-out scheduling policy.  Requires special (superuser, where such a thing exists) permissions. */
+#define SCHED_FIFO 1
+/*!\brief Real-time, round-robin scheduling policy.  Requires special (superuser, where such a thing exists) permissions. */
+#define SCHED_RR 0
+
+/*!\brief Creates a new thread with the given attributes, thread function and arguments, giving back the thread ID of the new
+ * thread.
+ *
+ * pthread_create() creates a new thread of control that executes concurrently with the calling thread.  The new thread applies the
+ * function start_routine, passing it arg as its argument.  The attr argument specifies thread attributes to apply to the new thread;
+ * it can also be NULL for the default thread attributes (joinable with default scheduling policy).  On success this function returns
+ * 0 and places the identifier of the new thread into thread_id.  On an error, pthread_create() can return EAGAIN if insufficient
+ * runtime resources are available to create the requested thread, EINVAL a value specified by attributes is invalid, or EPERM if the
+ * caller doesn't have permissions to set the given attributes.
+ *
+ * For further information: man 3 pthread_create */
+int32_t pthread_create(pthread_t *thread_id, const pthread_attr_t *attributes, pthread_function_t thread_function, void *arguments);
+/*!\brief Terminates the execution of the calling thread.  The thread's exit code with by status, and this routine never returns. */
+void pthread_exit(void *status);
+/*!\brief Returns the thread identifier of the calling thread. */
+pthread_t pthread_self();
+/*!\brief Compares two thread identifiers.
+ *
+ * Determines of the given two thread identifiers refer to the same thread.  If so, returns non-zero.  Otherwise, 0 is returned. */
+int32_t pthread_equal(pthread_t thread1, pthread_t thread2);
+/*!\brief Used by the calling thread to relinquish use of the processor.  The thread then waits in the run queue to be scheduled
+ * again. */
+void pthread_yield();
+
+/*!\brief Gets the scheduling policy of the given attributes.
+ *
+ * Places the scheduling policy for attributes into policy.  Returns 0 on success, EINVAL if attributes was invalid, and ENOSYS if
+ * priority scheduling/multiple scheduler support is not implemented. */
+int32_t pthread_attr_getschedpolicy(const pthread_attr_t *attributes, int32_t *policy);
+/*!\brief Sets the scheduling policy of the given attributes.
+ *
+ * Requests a switch of scheduling policy to policy for the given attributes.  Can return 0 for success, EINVAL if the given policy
+ * is not one of SCHED_OTHER, SCHED_FIFO or SCHED_RR or ENOTSUP if policy is either SCHED_FIFO or SCHED_RR and the driver is not
+ * running with correct privileges. */
+int32_t pthread_attr_setschedpolicy(pthread_attr_t *attributes, int32_t policy);
+
+/*!\brief Gets the scheduling paramaters (priority) from the given attributes.
+ *
+ * On success, stores scheduling parameters in param from attributes, and returns 0.  Otherwise, returns non-zero error code, such
+ * as EINVAL if the attributes object is invalid. */
+int32_t pthread_attr_getschedparam(const pthread_attr_t *attributes, sched_param *param);
+/*!\brief Sets the scheduling parameters (priority) of the given attributes.
+ *
+ * Requests that the runtime set the scheduling parameters (priority) of attributes from param. Returns 0 for success, EINVAL for an
+ * invalid attributes object, ENOSYS when multiple schedulers/priority scheduling is not implemented, and ENOTSUP when the value of
+ * param isn't supported/allowed. */
+int32_t pthread_attr_setschedparam(pthread_attr_t *attributes, const sched_param *param);
+
+/*!\brief The thread obtains its scheduling properties explicitly from its attributes structure. */
+#define PTHREAD_EXPLICIT_SCHED 1
+/*!\brief The thread inherits its scheduling properties from its parent thread. */
+#define PTHREAD_INHERIT_SCHED 0
+
+/*!\brief Returns the inheritsched attribute of the given attributes.
+ *
+ * On success, returns 0 and places the inheritsched attribute from attributes into inherit.  This attribute specifies where the
+ * thread's scheduling properites shall come from, and can be set to PTHREAD_EXPLICIT_SCHED or PTHREAD_INHERIT_SCHED.  On failure it
+ * returns EINVAL if attributes was invalid or ENOSYS if multiple schedulers/priority scheduling isn't implemented. */
+int32_t pthread_attr_getinheritsched(const pthread_attr_t *attributes, int32_t *inherit);
+/*!\brief Sets the inheritsched attribute of the given attributes.
+ *
+ * On success, places inherit into the inheritsched attribute of attributes and returns 0.  inherit must either contain
+ * PTHREAD_EXPLICIT_SCHED or PTHREAD_INHERIT_SCHED.  On failure, this routine returns EINVAL if attributes is invalid, ENOSYS when
+ * multiple schedulers/priority scheduling isn't implemented, and ENOSUP if the inheritsched attribute isn't supported. */
+int32_t pthread_attr_setinheritsched(pthread_attr_t *attributes, int32_t inherit);
+
+/*!\brief Creates a new POSIX Threads mutex, which will initially be unlocked.
+ *
+ * Creates a new mutex with the given attributes.  If attributes is NULL, the default attributes will be used.  The mutex starts out
+ * unlocked.  On success, the new mutex resides in the mutex structure pointed to by mutex, and this routine routines 0.  On failure,
+ * it returns EAGAIN if the system lacked sufficient non-memory resources to initialize the mutex, EBUSY if the given mutex is
+ * already initialized and in use, EINVAL if either parameter is invalid, and ENOMEM if the system lacks the memory for a new
+ * mutex.  Note: All EDI mutexes are created with the default attributes, and are of type PTHREAD_MUTEX_ERRORCHECK.  This means
+ * undefined behavior can never result from an badly placed function call. */
+int32_t pthread_mutex_init (pthread_mutex_t *mutex, const pthread_mutex_attr_t *attributes);
+/*!\brief Locks the given mutex.
+ *
+ * Locks the given mutex.  If the mutex is already locked, blocks the calling thread until it can acquire the lock.  When this
+ * routine returns successfully, it will return 0 and the calling thread will own the lock of the mutex.  If the call fails, it can
+ * return EINVAL when mutex is invalid or EDEADLK if the calling thread already owns the mutex. */
+int32_t pthread_mutex_lock(pthread_mutex_t *mutex);
+/*!\brief Unlocks the given mutex.
+ *
+ * Unlocks the given mutex, returning 0 on success.  On failure, it can return EINVAL when mutex is invalid or EPERM when the
+ * calling thread doesn't own the mutex. */
+int32_t pthread_mutex_unlock(pthread_mutex_t *mutex);
+/*!\brief Tries to lock the given mutex, returning immediately even if the mutex is already locked.
+ *
+ * Attempts to lock the given mutex, but returns immediately if it can't acquire a lock.  Returns 0 when it has acquired a lock,
+ * EBUSY if the mutex is already locked, or EINVAL if mutex is invalid. */
+int32_t pthread_mutex_trylock(pthread_mutex_t *mutex);
+/*!\brief Destroys the given mutex, or at least the internal structure of it. 
+ *
+ * Deletes the given mutex, making mutex invalid until it should be initialized by pthread_mutex_init().  Returns 0 on success,
+ * EINVAL when mutex is invalid, or EBUSY when mutex is locked or referenced by another thread. */
+int32_t pthread_mutex_destroy (pthread_mutex_t *mutex);
+
+#endif
diff --git a/Modules/Interfaces/EDI/edi/helpers.h b/Modules/Interfaces/EDI/edi/helpers.h
new file mode 100644 (file)
index 0000000..d7bc138
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef HELPERS_H
+
+#define HELPERS_H
+
+#include <edi.h>
+
+// Locally Defined
+bool edi_string_equal(edi_string_t x,edi_string_t y);
+bool descends_from(data_pointer object_class,edi_string_t desired_class);
+data_pointer get_actual_class(edi_string_t ancestor,int32_t num_objects,edi_object_metadata_t *objects);
+
+// Local Copy/set
+void *memcpyd(void *dest, void *src, unsigned int count);
+
+// Implementation Defined Common functions
+void *memcpy(void *dest, void *src, unsigned int count);
+void *memmove(void *dest, void *src, unsigned int count);
+void *realloc(void *ptr, unsigned int size);
+
+#endif
diff --git a/Modules/Interfaces/EDI/edi_int.inc.c b/Modules/Interfaces/EDI/edi_int.inc.c
new file mode 100644 (file)
index 0000000..0ab3359
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * AcessOS EDI Interface
+ * - IRQ Class
+ * 
+ * By John Hodge (thePowersGang)
+ * 
+ * This file has been released into the public domain.
+ * You are free to use it as you wish.
+ */
+#include "edi/edi.h"
+
+// === TYPES ===
+typedef struct {
+       uint16_t        State;  // 0: Unallocated, 1: Allocated, 2: Initialised, (Bit 0x8000 set if in heap)
+       uint16_t        Num;
+       interrupt_handler_t     Handler;
+} tEdiIRQ;
+
+// === PROTOTYPES ===
+void EDI_Int_IRQ_Handler(tRegs *Regs);
+
+// === GLOBALS ===
+tEdiIRQ        gEdi_IRQObjects[16];
+
+// === FUNCTIONS ===
+/**
+ * \fn object_pointer Edi_Int_IRQ_Construct(void)
+ * \brief Creates a new IRQ Object
+ * \return     Pointer to object
+ */
+object_pointer Edi_Int_IRQ_Construct(void)
+{
+        int    i;
+       // Search for a free irq
+       for( i = 0; i < 16; i ++ )
+       {
+               if(gEdi_IRQObjects[i].State)    continue;
+               gEdi_IRQObjects[i].State = 1;
+               gEdi_IRQObjects[i].Num = 0;
+               gEdi_IRQObjects[i].Handler = NULL;
+               return &gEdi_IRQObjects[i];
+       }
+       return NULL;
+}
+
+/**
+ * \fn void Edi_Int_IRQ_Destruct(object_pointer Object)
+ * \brief Destruct an IRQ Object
+ * \param Object       Object to destroy
+ */
+void Edi_Int_IRQ_Destruct(object_pointer Object)
+{
+       tEdiIRQ *obj;
+       
+       VALIDATE_PTR(Object,);
+       obj = GET_DATA(Object);
+       
+       if( !obj->State )       return;
+       
+       if( obj->Handler )
+               irq_uninstall_handler( obj->Num );
+       
+       if( obj->State & 0x8000 ) {     // If in heap, free
+               free(Object);
+       } else {        // Otherwise, mark as unallocated
+               obj->State = 0;
+       }
+}
+
+/**
+ * \fn int32_t Edi_Int_IRQ_InitInt(object_pointer Object, uint16_t Num, interrupt_handler_t Handler)
+ * \brief Initialises an IRQ
+ * \param Object       Object Pointer (this)
+ * \param Num  IRQ Number to use
+ * \param Handler      Callback for IRQ
+ */
+int32_t        Edi_Int_IRQ_InitInt(object_pointer Object, uint16_t Num, interrupt_handler_t Handler)
+{
+       tEdiIRQ *obj;
+       
+       //LogF("Edi_Int_IRQ_InitInt: (Object=0x%x, Num=%i, Handler=0x%x)\n", Object, Num, Handler);
+       
+       VALIDATE_PTR(Object,0);
+       obj = GET_DATA(Object);
+       
+       if( !obj->State )       return 0;
+       
+       if(Num > 15)    return 0;
+       
+       // Install the IRQ if a handler is passed
+       if(Handler) {
+               if( !irq_install_handler(Num, Edi_Int_IRQ_Handler) )
+                       return 0;
+               obj->Handler = Handler;
+       }
+       
+       obj->Num = Num;
+       obj->State &= ~0x3FFF;
+       obj->State |= 2;        // Set initialised flag
+       return 1;
+}
+
+/**
+ * \fn uint16_t Edi_Int_IRQ_GetInt(object_pointer Object)
+ * \brief Returns the irq number associated with the object
+ * \param Object       IRQ Object to get number from
+ * \return IRQ Number
+ */
+uint16_t Edi_Int_IRQ_GetInt(object_pointer Object)
+{
+       tEdiIRQ *obj;
+       
+       VALIDATE_PTR(Object,0);
+       obj = GET_DATA(Object);
+       
+       if( !obj->State )       return 0;
+       return obj->Num;
+}
+
+/**
+ * \fn void EDI_Int_IRQ_SetHandler(object_pointer Object, interrupt_handler_t Handler)
+ * \brief Set the IRQ handler for an IRQ object
+ * \param Object       IRQ Object to alter
+ * \param Handler      Function to use as handler
+ */
+void EDI_Int_IRQ_SetHandler(object_pointer Object, interrupt_handler_t Handler)
+{
+       tEdiIRQ *obj;
+       
+       // Get Data Pointer
+       VALIDATE_PTR(Object,);
+       obj = GET_DATA(Object);
+       
+       // Sanity Check arguments
+       if( !obj->State )       return ;
+       
+       // Only register the mediator if it is not already
+       if( Handler && !obj->Handler )
+               if( !irq_install_handler(obj->Num, Edi_Int_IRQ_Handler) )
+                       return ;
+       obj->Handler = Handler;
+}
+
+/**
+ * \fn void EDI_Int_IRQ_Return(object_pointer Object)
+ * \brief Return from interrupt
+ * \param Object       IRQ Object
+ * \note Due to the structure of acess interrupts, this is a dummy
+ */
+void EDI_Int_IRQ_Return(object_pointer Object)
+{
+}
+
+/**
+ * \fn void Edi_Int_IRQ_Handler(struct regs *Regs)
+ * \brief EDI IRQ Handler - Calls the handler 
+ * \param Regs Register state at IRQ call
+ */
+void Edi_Int_IRQ_Handler(struct regs *Regs)
+{
+        int    i;
+       for( i = 0; i < 16; i ++ )
+       {
+               if(!gEdi_IRQObjects[i].State)   continue;       // Unused, Skip
+               if(gEdi_IRQObjects[i].Num != Regs->int_no)      continue;       // Another IRQ, Skip
+               if(!gEdi_IRQObjects[i].Handler) continue;       // No Handler, Skip
+               gEdi_IRQObjects[i].Handler( Regs->int_no );     // Call Handler
+               return;
+       }
+}
+
+
+// === CLASS DECLARATION ===
+static edi_function_declaration_t      scEdi_Int_Functions_IRQ[] = {
+               {"int32_t", "init_interrupt", 1, 3, NULL, //scEdi_Int_Variables_IO[0],
+                       (function_pointer)Edi_Int_IRQ_InitInt
+                       },
+               {"uint32_t", "interrupt_get_irq", 1, 1, NULL, //scEdi_Int_Variables_IO[1],
+                       (function_pointer)Edi_Int_IRQ_GetInt
+                       },
+               {"void", "interrupt_set_handler", 1, 2, NULL, //scEdi_Int_Variables_IO[2],
+                       (function_pointer)Edi_Int_IRQ_GetInt
+                       },
+               {"void", "interrupt_return", 1, 1, NULL, //scEdi_Int_Variables_IO[3],
+                       (function_pointer)Edi_Int_IRQ_GetInt
+                       }
+       };
+static edi_class_declaration_t scEdi_Int_Class_IRQ = 
+       {
+               INTERRUPTS_CLASS, 1, 12,
+               scEdi_Int_Functions_IRQ,
+               Edi_Int_IRQ_Construct,
+               Edi_Int_IRQ_Destruct,
+               NULL
+       };
diff --git a/Modules/Interfaces/EDI/edi_io.inc.c b/Modules/Interfaces/EDI/edi_io.inc.c
new file mode 100644 (file)
index 0000000..8a6ef22
--- /dev/null
@@ -0,0 +1,391 @@
+/*
+ * AcessOS EDI Interface
+ * - IO Port Class
+ * 
+ * By John Hodge (thePowersGang)
+ * 
+ * This file has been released into the public domain.
+ * You are free to use it as you wish.
+ */
+#include "edi/edi.h"
+
+// === TYPES ===
+typedef struct {
+       uint16_t        State;  // 0: Unallocated, 1: Allocated, 2: Initialised, (Bit 0x8000 set if in heap)
+       uint16_t        Num;
+} tEdiPort;
+
+// === GLOBALS ===
+#define        NUM_PREALLOC_PORTS      128
+tEdiPort       gEdi_PortObjects[NUM_PREALLOC_PORTS];
+
+// === FUNCTIONS ===
+/**
+ * \fn object_pointer Edi_Int_IO_Construct(void)
+ * \brief Creates a new IO Port Object
+ * \return     Pointer to object
+ */
+object_pointer Edi_Int_IO_Construct(void)
+{
+       tEdiPort        *ret;
+        int    i;
+       // Search for a free preallocated port
+       for( i = 0; i < NUM_PREALLOC_PORTS; i ++ )
+       {
+               if(gEdi_PortObjects[i].State)   continue;
+               gEdi_PortObjects[i].State = 1;
+               gEdi_PortObjects[i].Num = 0;
+               return &gEdi_PortObjects[i];
+       }
+       // Else, use heap space
+       ret = malloc( sizeof(tEdiPort) );
+       ret->State = 0x8001;
+       ret->Num = 0;
+       return ret;
+}
+
+/**
+ * \fn void Edi_Int_IO_Destruct(object_pointer Object)
+ * \brief Destruct an IO Port Object
+ * \param Object       Object to destroy
+ */
+void Edi_Int_IO_Destruct(object_pointer Object)
+{
+       tEdiPort        *obj;
+       // Get Data Pointer
+       VALIDATE_PTR(Object,);
+       obj = GET_DATA(Object);
+       
+       if(obj->State & 0x8000) {       // If in heap, free
+               free(Object);
+       } else {        // Otherwise, mark as unallocated
+               obj->State = 0;
+       }
+}
+
+/**
+ * \fn int32_t Edi_Int_IO_InitPort(object_pointer Object, uint16_t Port)
+ * \brief Initialises an IO Port
+ * \param Object       Object Pointer (this)
+ * \param Port Port Number to use
+ */
+int32_t        Edi_Int_IO_InitPort(object_pointer Object, uint16_t Port)
+{
+       tEdiPort        *obj;
+       // Get Data Pointer
+       VALIDATE_PTR(Object, 0);
+       obj = GET_DATA(Object);
+       
+       if( !obj->State )       return 0;
+       obj->Num = Port;
+       obj->State &= ~0x3FFF;
+       obj->State |= 2;        // Set initialised flag
+       return 1;
+}
+
+/**
+ * \fn uint16_t Edi_Int_IO_GetPortNum(object_pointer Object)
+ * \brief Returns the port number associated with the object
+ * \param Object       Port Object to get number from
+ * \return Port Number
+ */
+uint16_t Edi_Int_IO_GetPortNum(object_pointer Object)
+{
+       tEdiPort        *obj;
+       // Get Data Pointer
+       VALIDATE_PTR(Object, 0);
+       obj = GET_DATA(Object);
+       // Check if valid
+       if( !obj->State )       return 0;
+       // Return Port No
+       return obj->Num;
+}
+
+/**
+ * \fn int32_t Edi_Int_IO_ReadByte(object_pointer Object, uint8_t *out)
+ * \brief Read a byte from an IO port
+ * \param Object       Port Object
+ * \param out  Pointer to put read data
+ */
+int32_t Edi_Int_IO_ReadByte(object_pointer Object, uint8_t *out)
+{
+       tEdiPort        *obj;
+       // Get Data Pointer
+       VALIDATE_PTR(Object, 0);
+       obj = GET_DATA(Object);
+       
+       if( !obj->State )       return 0;
+       if( obj->State & 1 )    return -1;      // Unintialised
+       
+       __asm__ __volatile__ ( "inb %%dx, %%al" : "=a" (*out) : "d" ( obj->Num ) );
+       
+       return 1;
+}
+
+/**
+ * \fn int32_t Edi_Int_IO_ReadWord(object_pointer Object, uint16_t *out)
+ * \brief Read a word from an IO port
+ * \param Object       Port Object
+ * \param out  Pointer to put read data
+ */
+int32_t Edi_Int_IO_ReadWord(object_pointer Object, uint16_t *out)
+{
+       
+       tEdiPort        *obj;
+       // Get Data Pointer
+       VALIDATE_PTR(Object, 0);
+       obj = GET_DATA(Object);
+       if( !obj->State )       return 0;
+       if( obj->State & 1 )    return -1;      // Unintialised
+       
+       __asm__ __volatile__ ( "inw %%dx, %%ax" : "=a" (*out) : "d" ( obj->Num ) );
+       
+       return 1;
+}
+
+/**
+ * \fn int32_t Edi_Int_IO_ReadDWord(object_pointer Object, uint32_t *out)
+ * \brief Read a double word from an IO port
+ * \param Object       Port Object
+ * \param out  Pointer to put read data
+ */
+int32_t Edi_Int_IO_ReadDWord(object_pointer Object, uint32_t *out)
+{
+       
+       tEdiPort        *obj;
+       // Get Data Pointer
+       VALIDATE_PTR(Object, 0);
+       obj = GET_DATA(Object);
+       if( !obj->State )       return 0;
+       if( obj->State & 1 )    return -1;      // Unintialised
+       
+       __asm__ __volatile__ ( "inl %%dx, %%eax" : "=a" (*out) : "d" ( obj->Num ) );
+       
+       return 1;
+}
+
+/**
+ * \fn int32_t Edi_Int_IO_ReadQWord(object_pointer Object, uint64_t *out)
+ * \brief Read a quad word from an IO port
+ * \param Object       Port Object
+ * \param out  Pointer to put read data
+ */
+int32_t Edi_Int_IO_ReadQWord(object_pointer Object, uint64_t *out)
+{
+       uint32_t        *out32 = (uint32_t*)out;
+       tEdiPort        *obj;
+       // Get Data Pointer
+       VALIDATE_PTR(Object, 0);
+       obj = GET_DATA(Object);
+       if( !obj->State )       return 0;
+       if( obj->State & 1 )    return -1;      // Unintialised
+       
+       __asm__ __volatile__ ( "inl %%dx, %%eax" : "=a" (*out32) : "d" ( obj->Num ) );
+       __asm__ __volatile__ ( "inl %%dx, %%eax" : "=a" (*(out32+1)) : "d" ( obj->Num+4 ) );
+       
+       return 1;
+}
+
+/**
+ * \fn int32_t Edi_Int_IO_ReadString(object_pointer Object, uint32_t Length, uint8_t *out)
+ * \brief Read a byte from an IO port
+ * \param Object       Port Object
+ * \param Length       Number of bytes to read
+ * \param out  Pointer to put read data
+ */
+int32_t Edi_Int_IO_ReadString(object_pointer Object, uint32_t Length, uint8_t *out)
+{
+       tEdiPort        *obj;
+       // Get Data Pointer
+       VALIDATE_PTR(Object, 0);
+       obj = GET_DATA(Object);
+       if( !obj->State )       return 0;
+       if( obj->State & 1 )    return -1;      // Unintialised
+       
+       __asm__ __volatile__ ( "rep insb" : : "c" (Length), "D" (out), "d" ( obj->Num ) );
+       
+       return 1;
+}
+
+/**
+ * \fn int32_t Edi_Int_IO_WriteByte(object_pointer Object, uint8_t in)
+ * \brief Write a byte from an IO port
+ * \param Object       Port Object
+ * \param in   Data to write
+ */
+int32_t Edi_Int_IO_WriteByte(object_pointer Object, uint8_t in)
+{
+       tEdiPort        *obj;
+       // Get Data Pointer
+       VALIDATE_PTR(Object, 0);
+       obj = GET_DATA(Object);
+       if( !obj->State )       return 0;
+       if( obj->State & 1 )    return -1;      // Unintialised
+       
+       __asm__ __volatile__ ( "outb %%al, %%dx" : : "a" (in), "d" ( obj->Num ) );
+       
+       return 1;
+}
+
+/**
+ * \fn int32_t Edi_Int_IO_WriteWord(object_pointer Object, uint16_t in)
+ * \brief Write a word from an IO port
+ * \param Object       Port Object
+ * \param in   Data to write
+ */
+int32_t Edi_Int_IO_WriteWord(object_pointer Object, uint16_t in)
+{
+       tEdiPort        *obj;
+       // Get Data Pointer
+       VALIDATE_PTR(Object, 0);
+       obj = GET_DATA(Object);
+       if( !obj->State )       return 0;
+       if( obj->State & 1 )    return -1;      // Unintialised
+       
+       __asm__ __volatile__ ( "outw %%ax, %%dx" : : "a" (in), "d" ( obj->Num ) );
+       
+       return 1;
+}
+
+/**
+ * \fn int32_t Edi_Int_IO_WriteDWord(object_pointer Object, uint32_t in)
+ * \brief Write a double word from an IO port
+ * \param Object       Port Object
+ * \param in   Data to write
+ */
+int32_t Edi_Int_IO_WriteDWord(object_pointer Object, uint32_t in)
+{
+       tEdiPort        *obj;
+       // Get Data Pointer
+       VALIDATE_PTR(Object, 0);
+       obj = GET_DATA(Object);
+       if( !obj->State )       return 0;
+       if( obj->State & 1 )    return -1;      // Unintialised
+       
+       __asm__ __volatile__ ( "outl %%eax, %%dx" : : "a" (in), "d" ( obj->Num ) );
+       
+       return 1;
+}
+
+/**
+ * \fn int32_t Edi_Int_IO_WriteQWord(object_pointer Object, uint64_t in)
+ * \brief Write a quad word from an IO port
+ * \param Object       Port Object
+ * \param in   Data to write
+ */
+int32_t Edi_Int_IO_WriteQWord(object_pointer Object, uint64_t in)
+{
+       uint32_t        *in32 = (uint32_t*)&in;
+       tEdiPort        *obj;
+       // Get Data Pointer
+       VALIDATE_PTR(Object, 0);
+       obj = GET_DATA(Object);
+       if( !obj->State )       return 0;
+       if( obj->State & 1 )    return -1;      // Unintialised
+       
+       __asm__ __volatile__ ( "outl %%eax, %%dx" : : "a" (*in32), "d" ( obj->Num ) );
+       __asm__ __volatile__ ( "outl %%eax, %%dx" : : "a" (*(in32+1)), "d" ( obj->Num+4 ) );
+       
+       return 1;
+}
+
+/**
+ * \fn int32_t Edi_Int_IO_WriteString(object_pointer Object, uint32_t Length, uint8_t *in)
+ * \brief Read a byte from an IO port
+ * \param Object       Port Object
+ * \param Length       Number of bytes to write
+ * \param in   Pointer to of data to write
+ */
+int32_t Edi_Int_IO_WriteString(object_pointer Object, uint32_t Length, uint8_t *in)
+{
+       tEdiPort        *obj;
+       // Get Data Pointer
+       VALIDATE_PTR(Object, 0);
+       obj = GET_DATA(Object);
+       if( !obj->State )       return 0;
+       if( obj->State & 1 )    return -1;      // Unintialised
+       
+       __asm__ __volatile__ ( "rep outsb" : : "c" (Length), "D" (in), "d" ( obj->Num ) );
+       
+       return 1;
+}
+
+// === CLASS DECLARATION ===
+/*static edi_variable_declaration_t    *scEdi_Int_Variables_IO[] = {
+       {
+               {"pointer", "port_object", 0},
+               {"uint16_t", "port", 0}
+       },
+       {
+               {"pointer", "port_object", 0}
+       },
+       {
+               {"pointer", "port_object", 0},
+               {"pointer int8_t", "out", 0}
+       }
+};*/
+static edi_function_declaration_t      scEdi_Int_Functions_IO[] = {
+               {"int32_t", "init_io_port", 1, 2, NULL, //scEdi_Int_Variables_IO[0],
+                       (function_pointer)Edi_Int_IO_InitPort
+                       },
+               {"uint16_t", "get_port_number", 1, 1, NULL, //scEdi_Int_Variables_IO[1],
+                       (function_pointer)Edi_Int_IO_GetPortNum
+                       },
+               {"int32_t", "read_byte_io_port", 1, 2, NULL, //scEdi_Int_Variables_IO[2],
+                       (function_pointer)Edi_Int_IO_ReadByte
+                       },
+               {"int32_t", "read_word_io_port", 1, 2, NULL/*{
+                               {"pointer", "port_object", 0},
+                               {"pointer int16_t", "out", 0}
+                       }*/,
+                       (function_pointer)Edi_Int_IO_ReadWord
+                       },
+               {"int32_t", "read_long_io_port", 1, 2, NULL/*{
+                               {"pointer", "port_object", 0},
+                               {"pointer int32_t", "out", 0}
+                       }*/,
+                       (function_pointer)Edi_Int_IO_ReadDWord
+                       },
+               {"int32_t", "read_longlong_io_port", 1, 2, NULL/*{
+                               {"pointer", "port_object", 0},
+                               {"pointer int64_t", "out", 0}
+                       }*/,
+                       (function_pointer)Edi_Int_IO_ReadQWord
+                       },
+               {"int32_t", "read_string_io_port", 1, 3, NULL/*{
+                               {"pointer", "port_object", 0},
+                               {"int32_T", "data_length", 0},
+                               {"pointer int64_t", "out", 0}
+                       }*/,
+                       (function_pointer)Edi_Int_IO_ReadString
+                       },
+                       
+               {"int32_t", "write_byte_io_port", 1, 2, NULL/*{
+                               {"pointer", "port_object", 0},
+                               {"int8_t", "in", 0}
+                       }*/,
+                       (function_pointer)Edi_Int_IO_WriteByte},
+               {"int32_t", "write_word_io_port", 1, 2, NULL/*{
+                               {"pointer", "port_object", 0},
+                               {"int16_t", "in", 0}
+                       }*/,
+                       (function_pointer)Edi_Int_IO_WriteWord},
+               {"int32_t", "write_long_io_port", 1, 2, NULL/*{
+                               {"pointer", "port_object", 0},
+                               {"int32_t", "in", 0}
+                       }*/,
+                       (function_pointer)Edi_Int_IO_WriteDWord},
+               {"int32_t", "write_longlong_io_port", 1, 2, NULL/*{
+                               {"pointer", "port_object", 0},
+                               {"int64_t", "in", 0}
+                       }*/,
+                       (function_pointer)Edi_Int_IO_WriteQWord}
+       };
+static edi_class_declaration_t scEdi_Int_Class_IO = 
+       {
+               IO_PORT_CLASS, 1, 12,
+               scEdi_Int_Functions_IO,
+               Edi_Int_IO_Construct,
+               Edi_Int_IO_Destruct,
+               NULL
+       };
diff --git a/Modules/Interfaces/EDI/main.c b/Modules/Interfaces/EDI/main.c
new file mode 100644 (file)
index 0000000..c3d0272
--- /dev/null
@@ -0,0 +1,496 @@
+/*
+ * Acess2 EDI Layer
+ */
+#define DEBUG  0
+#define VERSION        ((0<<8)|1)
+#include <acess.h>
+#include <modules.h>
+#include <fs_devfs.h>
+#define        IMPLEMENTING_EDI        1
+#include "edi/edi.h"
+
+#define        VALIDATE_PTR(_ptr,_err) do{if(!(_ptr))return _err; }while(0)
+#define        GET_DATA(_ptr)  (Object)
+
+#include "edi_io.inc.c"
+#include "edi_int.inc.c"
+
+// === STRUCTURES ===
+typedef struct sAcessEdiDriver {
+       struct sAcessEdiDriver  *Next;
+       tDevFS_Driver   Driver;
+        int    FileCount;
+       struct {
+               char    *Name;
+               tVFS_Node       Node;
+       }       *Files;
+       edi_object_metadata_t   *Objects;
+       edi_initialization_t    Init;
+       driver_finish_t Finish;
+} tAcessEdiDriver;
+
+// === PROTOTYPES ===
+ int   EDI_Install(char **Arguments);
+ int   EDI_DetectDriver(void *Base);
+ int   EDI_LoadDriver(void *Base);
+vfs_node *EDI_FS_ReadDir(vfs_node *Node, int Pos);
+vfs_node *EDI_FS_FindDir(vfs_node *Node, char *Name);
+ int   EDI_FS_CharRead(vfs_node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
+ int   EDI_FS_CharWrite(vfs_node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
+ int   EDI_FS_IOCtl(vfs_node *Node, int Id, void *Data);
+data_pointer EDI_GetInternalClass(edi_string_t ClassName);
+
+// === GLOBALS ===
+MODULE_DEFINE(0, VERSION, EDI, EDI_Install, NULL, NULL);
+tModuleLoader  gEDI_Loader = {
+       NULL, "EDI", EDI_DetectDriver, EDI_LoadDriver, NULL
+};
+tSpinlock      glEDI_Drivers;
+tAcessEdiDriver        *gEdi_Drivers = NULL;
+edi_class_declaration_t        *gcEdi_IntClasses[] = {
+       &scEdi_Int_Class_IO, &scEdi_Int_Class_IRQ
+};
+#define        NUM_INT_CLASSES (sizeof(gcEdi_IntClasses)/sizeof(gcEdi_IntClasses[0]))
+char *csCharNumbers[] = {"c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9"};
+char *csBlockNumbers[] = {"blk0", "blk1", "blk2", "blk3", "blk4", "blk5", "blk6", "blk7", "blk8", "blk9"};
+
+// === CODE ===
+/**
+ * \fn int EDI_Install(char **Arguments)
+ * \brief Stub intialisation routine
+ */
+int EDI_Install(char **Arguments)
+{
+       Module_RegisterLoader( &gEDI_Loader );
+       return 1;
+}
+
+/**
+ * \brief Detects if a driver should be loaded by the EDI subsystem
+ */
+int EDI_DetectDriver(void *Base)
+{
+       if( Binary_FindSymbol(BASE, "driver_init", NULL) == 0 )
+               return 0;
+       
+       return 1;
+}
+
+/**
+ * \fn int Edi_LoadDriver(void *Base)
+ * \brief Load an EDI Driver from a loaded binary
+ * \param Base Binary Handle
+ * \return 0 on success, non zero on error
+ */
+int EDI_LoadDriver(void *Base)
+{
+       driver_init_t   init;
+       driver_finish_t finish;
+       tAcessEdiDriver *info;
+        int    i, j;
+        int    devfsId;
+       edi_class_declaration_t *classes;
+
+       ENTER("pBase", Base);
+       
+       // Get Functions
+       if( !Binary_FindSymbol(Base, "driver_init", (Uint*)&init)
+       ||      !Binary_FindSymbol(Base, "driver_finish", (Uint*)&finish) )
+       {
+               Warning("[EDI  ] Driver %p does not provide both `driver_init` and `driver_finish`\n", Base);
+               Binary_Unload(Base);
+               return 0;
+       }
+       
+       // Allocate Driver Information
+       info = malloc( sizeof(tAcessEdiDriver) );
+       info->Finish = finish;
+       
+       // Initialise Driver
+       info->Init = init( 0, NULL );   // TODO: Implement Resources
+       
+       LOG("info->Init.driver_name = '%s'", info->Init.driver_name);
+       LOG("info->Init.num_driver_classes = %i", info->Init.num_driver_classes);
+       
+       // Count mappable classes
+       classes = info->Init.driver_classes;
+       info->FileCount = 0;
+       info->Objects = NULL;
+       for( i = 0, j = 0; i < info->Init.num_driver_classes; i++ )
+       {
+               if( strncmp(classes[i].name, "EDI-CHARACTER-DEVICE", 32) == 0 )
+               {
+                       data_pointer    *obj;
+                       // Initialise Object Instances
+                       for( ; (obj = classes[i].constructor()); j++ ) {
+                               LOG("%i - Constructed '%s'", j, classes[i].name);
+                               info->FileCount ++;
+                               info->Objects = realloc(info->Objects, sizeof(*info->Objects)*info->FileCount);
+                               info->Objects[j].object = obj;
+                               info->Objects[j].object_class = &classes[i];
+                       }
+               }
+               else
+                       LOG("%i - %s", i, classes[i].name);
+       }
+       
+       if(info->FileCount)
+       {
+                int    iNumChar = 0;
+               // Create VFS Nodes
+               info->Files = malloc( info->FileCount * sizeof(*info->Files) );
+               memset(info->Files, 0, info->FileCount * sizeof(*info->Files));
+               j = 0;
+               for( j = 0; j < info->FileCount; j++ )
+               {
+                       classes = info->Objects[j].object_class;
+                       if( strncmp(classes->name, "EDI-CHARACTER-DEVICE", 32) == 0 )
+                       {
+                               LOG("%i - %s", j, csCharNumbers[iNumChar]);
+                               info->Files[j].Name = csCharNumbers[iNumChar];
+                               info->Files[j].Node.NumACLs = 1;
+                               info->Files[j].Node.ACLs = &gVFS_ACL_EveryoneRW;
+                               info->Files[j].Node.ImplPtr = &info->Objects[j];
+                               info->Files[j].Node.Read = EDI_FS_CharRead;
+                               info->Files[j].Node.Write = EDI_FS_CharWrite;
+                               info->Files[j].Node.IOCtl = EDI_FS_IOCtl;
+                               info->Files[j].Node.CTime =
+                                       info->Files[j].Node.MTime =
+                                       info->Files[j].Node.ATime = now();
+                               
+                               iNumChar ++;
+                               continue;
+                       }
+               }
+               
+               // Create DevFS Driver
+               info->Driver.ioctl = EDI_FS_IOCtl;
+               memsetda(&info->Driver.rootNode, 0, sizeof(vfs_node) / 4);
+               info->Driver.Name = info->Init.driver_name;
+               info->Driver.RootNode.Flags = VFS_FFLAG_DIRECTORY;
+               info->Driver.RootNode.NumACLs = 1;
+               info->Driver.RootNode.ACLs = &gVFS_ACL_EveryoneRX;
+               info->Driver.RootNode.Length = info->FileCount;
+               info->Driver.RootNode.ImplPtr = info;
+               info->Driver.RootNode.ReadDir = EDI_FS_ReadDir;
+               info->Driver.RootNode.FindDir = EDI_FS_FindDir;
+               info->Driver.RootNode.IOCtl = EDI_FS_IOCtl;
+               
+               // Register
+               devfsId = dev_addDevice( &info->Driver );
+               if(devfsId == -1) {
+                       free(info->Files);      // Free Files
+                       info->Finish(); // Clean up driver
+                       free(info);             // Free info structure
+                       Binary_Unload(iDriverBase);     // Unload library
+                       return -3;      // Return error
+               }
+       }
+       
+       // Append to loaded list;
+       LOCK(&glEDI_Drivers);
+       info->Next = gEDI_Drivers;
+       gEDI_Drivers = info;
+       RELEASE(&glEDI_Drivers);
+       
+       LogF("[EDI ] Loaded Driver '%s' (%s)\n", info->Init.driver_name, Path);
+       LEAVE('i', 1);
+       return 1;
+}
+
+// --- Filesystem Interaction ---
+/**
+ * \brief Read from a drivers class list
+ * \param Node Driver's Root Node
+ * \param Pos  Index of file to get
+ */
+char *EDI_FS_ReadDir(tVFS_Node *Node, int Pos)
+{
+       tAcessEdiDriver *info;
+       
+       // Sanity Check
+       if(!Node)       return NULL;
+       
+       // Get Information Structure
+       info = (void *) Node->ImplPtr;
+       if(!info)       return NULL;
+       
+       // Check Position
+       if(Pos < 0)     return NULL;
+       if(Pos >= info->FileCount)      return NULL;
+       
+       return strdup( info->Files[Pos].Name );
+}
+
+/**
+ * \fn tVFS_Node *EDI_FS_FindDir(tVFS_Node *Node, char *Name)
+ * \brief Find a named file in a driver
+ * \param Node Driver's Root Node
+ * \param Name Name of file to find
+ */
+tVFS_Node *EDI_FS_FindDir(tVFS_Node *Node, char *Name)
+{
+       tAcessEdiDriver *info;
+        int    i;
+       
+       // Sanity Check
+       if(!Node)       return NULL;
+       if(!Name)       return NULL;
+       
+       // Get Information Structure
+       info = (void *) Node->ImplPtr;
+       if(!info)       return NULL;
+       
+       for( i = 0; i < info->FileCount; i++ )
+       {
+               if(strcmp(info->Files[i].name, Name) == 0)
+                       return &info->Files[i].Node;
+       }
+       
+       return NULL;
+}
+
+/**
+ * \fn Uint64 EDI_FS_CharRead(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
+ * \brief Read from an EDI Character Device
+ * \param Node File Node
+ * \param Offset       Offset into file (ignored)
+ * \param Length       Number of characters to read
+ * \param Buffer       Destination for data
+ * \return     Number of characters read
+ */
+Uint64 EDI_FS_CharRead(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
+{
+       edi_object_metadata_t   *meta;
+       edi_class_declaration_t *class;
+       
+       // Sanity Check
+       if(!Node || !Buffer)    return 0;
+       if(Length <= 0) return 0;
+       // Get Object Metadata
+       meta = (void *) Node->ImplPtr;
+       if(!meta)       return 0;
+       
+       // Get Class
+       class = meta->object_class;
+       if(!class)      return 0;
+       
+       // Read from object
+       if( ((tAnyFunction) class->methods[0].code)( meta->object, Buffer, Length ))
+               return Length;
+
+       return 0;
+}
+
+/**
+ * \fn Uint64 EDI_FS_CharWrite(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
+ * \brief Write to an EDI Character Device
+ * \param Node File Node
+ * \param Offset       Offset into file (ignored)
+ * \param Length       Number of characters to write
+ * \param Buffer       Source for data
+ * \return     Number of characters written
+ */
+Uint64 EDI_FS_CharWrite(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
+{
+       edi_object_metadata_t   *meta;
+       edi_class_declaration_t *class;
+       
+       // Sanity Check
+       if(!Node || !Buffer)    return 0;
+       if(Length <= 0) return 0;
+       // Get Object Metadata
+       meta = (void *) Node->ImplPtr;
+       if(!meta)       return 0;
+       
+       // Get Class
+       class = meta->object_class;
+       if(!class)      return 0;
+       
+       // Write to object
+       if( ((tAnyFunction) class->methods[1].code)( meta->object, Buffer, Length ))
+               return Length;
+
+       return 0;
+}
+
+/**
+ * \fn int EDI_FS_IOCtl(tVFS_Node *Node, int Id, void *Data)
+ * \brief Perfom an IOCtl call on the object
+ */
+int EDI_FS_IOCtl(tVFS_Node *Node, int Id, void *Data)
+{
+       return 0;
+}
+
+// --- EDI Functions ---
+/**
+ * \fn data_pointer EDI_GetDefinedClass(edi_string_t ClassName)
+ * \brief Gets the structure of a driver defined class
+ * \param ClassName    Name of class to find
+ * \return Class definition or NULL
+ */
+data_pointer EDI_GetDefinedClass(edi_string_t ClassName)
+{
+        int    i;
+       tAcessEdiDriver *drv;
+       edi_class_declaration_t *classes;
+       
+       for(drv = gEdi_Drivers;
+               drv;
+               drv = drv->Next )
+       {
+               classes = drv->Init.driver_classes;
+               for( i = 0; i < drv->Init.num_driver_classes; i++ )
+               {
+                       if( strncmp(classes[i].name, ClassName, 32) == 0 )
+                               return &classes[i];
+               }
+       }
+       return NULL;
+}
+
+/**
+ * \fn int32_t EDI_CheckClassExistence(edi_string_t ClassName)
+ * \brief Checks if a class exists
+ * \param ClassName    Name of class
+ * \return 1 if the class exists, -1 otherwise
+ */
+int32_t EDI_CheckClassExistence(edi_string_t ClassName)
+{
+       //LogF("check_class_existence: (ClassName='%s')\n", ClassName);
+       if(EDI_GetInternalClass(ClassName))
+               return 1;
+               
+       if(EDI_GetDefinedClass(ClassName))      // Driver Defined
+               return 1;
+       
+       return -1;
+}
+
+/**
+ * \fn edi_object_metadata_t EDI_ConstructObject(edi_string_t ClassName)
+ * \brief Construct an instance of an class (an object)
+ * \param ClassName    Name of the class to construct
+ */
+edi_object_metadata_t EDI_ConstructObject(edi_string_t ClassName)
+{
+       edi_object_metadata_t   ret = {0, 0};
+       edi_class_declaration_t *class;
+       
+       //LogF("EDI_ConstructObject: (ClassName='%s')\n", ClassName);
+       
+       // Get class definition
+       if( !(class = EDI_GetInternalClass(ClassName)) )        // Internal
+               if( !(class = EDI_GetDefinedClass(ClassName)) ) // Driver Defined
+                       return ret;             // Return ERROR
+       
+       // Initialise
+       ret.object = class->constructor();
+       if( !ret.object )
+               return ret;     // Return ERROR
+       
+       // Set declaration pointer
+       ret.object_class = class;
+       
+       //LogF("EDI_ConstructObject: RETURN {0x%x,0x%x}\n", ret.object, ret.object_class);
+       return ret;
+}
+
+/**
+ * \fn void EDI_DestroyObject(edi_object_metadata_t Object)
+ * \brief Destroy an instance of a class
+ * \param Object       Object to destroy
+ */
+void EDI_DestroyObject(edi_object_metadata_t Object)
+{
+       if( !Object.object )    return;
+       if( !Object.object_class )      return;
+       
+       ((edi_class_declaration_t*)(Object.object_class))->destructor( &Object );
+}
+
+/**
+ * \fn function_pointer EDI_GetMethodByName(data_pointer ObjectClass, edi_string_t MethodName)
+ * \brief Get a method of a class by it's name
+ * \param ObjectClass  Pointer to a ::edi_object_metadata_t of the object
+ * \param MethodName   Name of the desired method
+ * \return Function address or NULL
+ */
+function_pointer EDI_GetMethodByName(data_pointer ObjectClass, edi_string_t MethodName)
+{
+       edi_class_declaration_t *dec = ObjectClass;
+        int    i;
+       
+       //LogF("get_method_by_name: (ObjectClass=0x%x, MethodName='%s')\n", ObjectClass, MethodName);
+       
+       if(!ObjectClass)        return NULL;
+       
+       for(i = 0; i < dec->num_methods; i++)
+       {
+               if(strncmp(MethodName, dec->methods[i].name, 32) == 0)
+                       return dec->methods[i].code;
+       }
+       return NULL;
+}
+
+#if 0
+function_pointer get_method_by_declaration(data_pointer Class, edi_function_declaration_t Declaration);
+#endif
+
+/**
+ * \fn edi_string_ptr_t EDI_GetClassParent(edi_string_t ClassName)
+ * \brief Get the parent of the named class
+ * \todo Implement
+ */
+edi_string_ptr_t EDI_GetClassParent(edi_string_t ClassName)
+{
+       WarningEx("EDI", "`get_class_parent` is unimplemented");
+       return NULL;
+}
+
+/**
+ * \fn data_pointer EDI_GetInternalClass(edi_string_t ClassName)
+ * \brief Get a builtin class
+ * \param ClassName    Name of class to find
+ * \return Pointer to the ::edi_class_declaration_t of the class
+ */
+data_pointer EDI_GetInternalClass(edi_string_t ClassName)
+{
+        int    i;
+       //LogF("get_internal_class: (ClassName='%s')\n", ClassName);
+       for( i = 0; i < NUM_INT_CLASSES; i++ )
+       {
+               if( strncmp( gcEdi_IntClasses[i]->name, ClassName, 32 ) == 0 ) {
+                       return gcEdi_IntClasses[i];
+               }
+       }
+       //LogF("get_internal_class: RETURN NULL\n");
+       return NULL;
+}
+
+/**
+ * \fn edi_string_ptr_t EDI_GetObjectClass(data_pointer Object)
+ * \brief Get the name of the object of \a Object
+ * \param Object       Object to get name of
+ * \return Pointer to the class name
+ */
+edi_string_ptr_t EDI_GetObjectClass(data_pointer ObjectClass)
+{
+       edi_object_metadata_t   *Metadata = ObjectClass;
+       // Sanity Check
+       if(!ObjectClass)        return NULL;
+       if(!(edi_class_declaration_t*) Metadata->object_class)  return NULL;
+       
+       // Return Class Name
+       return ((edi_class_declaration_t*) Metadata->object_class)->name;
+}
+
+// === EXPORTS ===
+EXPORTAS(EDI_CheckClassExistence, check_class_existence);
+EXPORTAS(EDI_ConstructObject, construct_object);
+EXPORTAS(EDI_DestroyObject, destroy_object);
+EXPORTAS(EDI_GetMethodByName, get_method_by_name);
+EXPORTAS(EDI_GetClassParent, get_class_parent);
+EXPORTAS(EDI_GetInternalClass, get_internal_class);
+EXPORTAS(EDI_GetObjectClass, get_object_class);
index 78be97b..b615dfe 100644 (file)
@@ -1,23 +1,17 @@
 /**
  * \file cb.c
  * \author John Hodge (thePowersGang)
+ * \brief Control block code
  */
 #include <acess.h>
 #include <udi.h>
 
-// === EXPORTS ===
-EXPORT(udi_cb_alloc);
-EXPORT(udi_cb_alloc_dynamic);
-EXPORT(udi_cb_alloc_batch);
-EXPORT(udi_cb_free);
-EXPORT(udi_cancel);
-
 // === CODE ===
 void udi_cb_alloc (
-       udi_cb_alloc_call_t *callback,
-       udi_cb_t *gcb,
-       udi_index_t cb_idx,
-       udi_channel_t default_channel
+       udi_cb_alloc_call_t     *callback,      //!< Function to be called when the CB is allocated
+       udi_cb_t        *gcb,   //!< Parent Control Block
+       udi_index_t     cb_idx,
+       udi_channel_t   default_channel
        )
 {
        UNIMPLEMENTED();
@@ -36,8 +30,8 @@ void udi_cb_alloc_dynamic(
 }
 
 void udi_cb_alloc_batch(
-       udi_cb_alloc_batch_call_t       *callback,
-       udi_cb_t        *gcb,
+       udi_cb_alloc_batch_call_t       *callback,      //!< 
+       udi_cb_t        *gcb,   //!< 
        udi_index_t     cb_idx,
        udi_index_t     count,
        udi_boolean_t   with_buf,
@@ -57,3 +51,10 @@ void udi_cancel(udi_cancel_call_t *callback, udi_cb_t *gcb)
 {
        UNIMPLEMENTED();
 }
+
+// === EXPORTS ===
+EXPORT(udi_cb_alloc);
+EXPORT(udi_cb_alloc_dynamic);
+EXPORT(udi_cb_alloc_batch);
+EXPORT(udi_cb_free);
+EXPORT(udi_cancel);
index d114bdc..a6fed92 100644 (file)
@@ -26,7 +26,7 @@ tModuleLoader gUDI_Loader = {
 int UDI_Install(char **Arguments)
 {
        Module_RegisterLoader( &gUDI_Loader );
-       return 1;
+       return MODULE_ERR_OK;
 }
 
 /**
index 4ab1e20..53cc933 100644 (file)
@@ -11,6 +11,12 @@ EXPORT(udi_snprintf);
 // === CODE ===
 udi_size_t udi_snprintf(char *s, udi_size_t max_bytes, const char *format, ...)
 {
-       s[0] = '\0';
-       return 0;
+       udi_size_t      ret;
+       va_list args;
+       va_start(args, format);
+       
+       ret = vsnprintf(s, max_bytes, format, args);
+       
+       va_end(args);
+       return ret;
 }
index 964f5ce..9a1b6e8 100644 (file)
@@ -12,10 +12,14 @@ CFGFILES += $(shell test -f Makefile.cfg && echo Makefile.cfg)
 -include $(CFGFILES)
 
 CPPFLAGS = -I$(ACESSDIR)/Kernel/include -I$(ACESSDIR)/Kernel/arch/$(ARCHDIR)/include -DARCH=$(ARCH) $(_CPPFLAGS)
-CFLAGS = -Wall -Werror -fno-stack-protector $(CPPFLAGS)
+CFLAGS = -Wall -Werror -fno-stack-protector $(CPPFLAGS) -O3
 
 OBJ := $(addsuffix .$(ARCH),$(OBJ))
-BIN = ../$(NAME).kmd.$(ARCH)
+ifneq ($(CATEGORY),)
+       BIN := ../$(CATEGORY)_$(NAME).kmd.$(ARCH)
+else
+       BIN := ../$(NAME).kmd.$(ARCH)
+endif
 KOBJ = ../$(NAME).xo.$(ARCH)
 
 DEPFILES  = $(filter %.o.$(ARCH),$(OBJ))
index 80c6d4d..d5c0b3c 100644 (file)
@@ -1 +1,3 @@
+CATEGORY = Network
+
 -include ../../Makefile.tpl
index 14314b8..f3fadda 100644 (file)
@@ -127,6 +127,11 @@ int Ne2k_Install(char **Options)
                giNe2k_CardCount += PCI_CountDevices( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device, 0 );
        }
        
+       if( giNe2k_CardCount == 0 ) {
+               Log_Warning("Ne2k", "No cards detected");
+               return MODULE_ERR_NOTNEEDED;
+       }
+       
        // Enumerate Cards
        k = 0;
        gpNe2k_Cards = calloc( giNe2k_CardCount, sizeof(tCard) );
@@ -194,12 +199,11 @@ int Ne2k_Install(char **Options)
                        Ne2k_WriteReg(base, MAC5, gpNe2k_Cards[ k ].MacAddr[5]);
                        */
                        
-                       Log("[NE2K]: Card #%i: IRQ=%i, IOBase=0x%x",
-                               k, gpNe2k_Cards[ k ].IRQ, gpNe2k_Cards[ k ].IOBase);
-                       Log("MAC Address %x:%x:%x:%x:%x:%x",
-                               gpNe2k_Cards[ k ].MacAddr[0], gpNe2k_Cards[ k ].MacAddr[1],
-                               gpNe2k_Cards[ k ].MacAddr[2], gpNe2k_Cards[ k ].MacAddr[3],
-                               gpNe2k_Cards[ k ].MacAddr[4], gpNe2k_Cards[ k ].MacAddr[5]
+                       Log_Log("Ne2k", "Card %i 0x%04x IRQ%i %02x:%02x:%02x:%02x:%02x:%02x",
+                               k, base, gpNe2k_Cards[ k ].IRQ,
+                               gpNe2k_Cards[k].MacAddr[0], gpNe2k_Cards[k].MacAddr[1],
+                               gpNe2k_Cards[k].MacAddr[2], gpNe2k_Cards[k].MacAddr[3],
+                               gpNe2k_Cards[k].MacAddr[4], gpNe2k_Cards[k].MacAddr[5]
                                );
                        
                        // Set VFS Node
@@ -216,7 +220,7 @@ int Ne2k_Install(char **Options)
        
        gNe2k_DriverInfo.RootNode.Size = giNe2k_CardCount;
        DevFS_AddDevice( &gNe2k_DriverInfo );
-       return 1;
+       return MODULE_ERR_OK;
 }
 
 /**
@@ -308,7 +312,8 @@ Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
        
        // Sanity Check Length
        if(Length > TX_BUF_SIZE*256) {
-               Warning(
+               Log_Warning(
+                       "Ne2k",
                        "Ne2k_Write - Attempting to send over TX_BUF_SIZE*256 (%i) bytes (%i)",
                        TX_BUF_SIZE*256, Length
                        );
@@ -506,5 +511,5 @@ void Ne2k_IRQHandler(int IntNum)
                        return ;
                }
        }
-       Warning("[NE2K ] Recieved Unknown IRQ %i", IntNum);
+       Log_Warning("Ne2k", "Recieved Unknown IRQ %i", IntNum);
 }
diff --git a/Modules/Network/RTL8139/main.c b/Modules/Network/RTL8139/main.c
new file mode 100644 (file)
index 0000000..aa7a444
--- /dev/null
@@ -0,0 +1,124 @@
+/* Acess2 RTL8139 Driver
+ * - By John Hodge (thePowersGang)
+ * 
+ * main.c - Driver Core
+ */
+#define        DEBUG   0
+#define VERSION        ((0<<8)|50)
+#include <acess.h>
+#include <modules.h>
+#include <fs_devfs.h>
+#include <drv_pci.h>
+#include <tpl_drv_network.h>
+
+// === CONSTANTS ===
+enum eRTL8139_Regs
+{
+       MAC0, MAC1, MAC2,
+       MAC3, MAC4, MAC5,
+       MAR0    = 0x08,
+       MAR1, MAR2, MAR3,
+       MAR4, MAR5, MAR6, MAR7,
+       
+       RBSTART = 0x30, //!< Recieve Buffer Start
+       // ??, ??, ??, RST, RE, TE, ??, ??
+       CMD     = 0x37,
+       IMR     = 0x3C,
+       ISR     = 0x3E,
+       
+       RCR     = 0x44,
+       
+       CONFIG1 = 0x52
+};
+
+// === TYPES ===
+typedef struct sCard
+{
+       Uint16  IOBase;
+       Uint8   IRQ;
+       
+        int    NumWaitingPackets;
+       
+       void    *ReceiveBuffer;
+       tPAddr  PhysReceiveBuffer;
+       
+       char    Name[2];
+       tVFS_Node       Node;
+       Uint8   MacAddr[6];
+}      tCard;
+
+// === PROTOTYPES ===
+
+// === GLOBALS ===
+MODULE_DEFINE(0, VERSION, RTL8139, RTL8139_Install, NULL, NULL);
+ int   giRTL8139_CardCount;
+tCard  gpRTL8139_Cards;
+
+// === CODE ===
+/**
+ * \brief Installs the RTL8139 Driver
+ */
+int RTL8139_Install(char **Options)
+{
+        int    id = -1;
+        int    i = 0;
+       Uint16  base;
+       
+       giRTL8139_CardCount = PCI_CountDevices( 0x10EC, 0x8139, 0 );
+       
+       gpRTL8139_Cards = calloc( giRTL8139_CardCount, sizeof(tCard) );
+       
+       
+       while( (id = PCI_GetDevice(0x10EC, 0x8139, 0, id)) != -1 )
+       {
+               base = PCI_AssignPort( id, 0, 0x100 );
+               gpRTL8139_Cards[i].IOBase = base;
+               gpRTL8139_Cards[i].IRQ = PCI_GetIRQ( id );
+               
+               // Install IRQ Handler
+               IRQ_AddHandler(gpRTL8139_Cards[ k ].IRQ, RTL8136_IRQHandler);
+               
+               // Power on
+               outb( base + CONFIG1, 0x00 );
+               // Reset (0x10 to CMD)
+               outb( base + CMD, 0x10 );
+               
+               gpRTL8139_Cards[i].ReceiveBuffer = MM_AllocDMA( 2, 32, &gpRTL8139_Cards[i].PhysReceiveBuffer );
+               // Set up recieve buffer
+               outl(base + RBSTART, (Uint32)gpRTL8139_Cards[i].PhysReceiveBuffer);
+               // Set IMR to Transmit OK and Receive OK
+               outw(base + IMR, 0x5);
+               
+               // Set recieve buffer size, buffer wrap and recieve mask
+               outl(base + RCR, 0x8F);
+               
+               outb(base + CMD, 0x0C); // Recive Enable and Transmit Enable
+               
+               gpRTL8139_Cards[ i ].MacAddr[0] = inb(base+MAC0);
+               gpRTL8139_Cards[ i ].MacAddr[1] = inb(base+MAC1);
+               gpRTL8139_Cards[ i ].MacAddr[2] = inb(base+MAC2);
+               gpRTL8139_Cards[ i ].MacAddr[3] = inb(base+MAC3);
+               gpRTL8139_Cards[ i ].MacAddr[4] = inb(base+MAC4);
+               gpRTL8139_Cards[ i ].MacAddr[5] = inb(base+MAC5);
+               
+               // Set VFS Node
+               gpRTL8139_Cards[ i ].Name[0] = '0'+i;
+               gpRTL8139_Cards[ i ].Name[1] = '\0';
+               gpRTL8139_Cards[ i ].Node.ImplPtr = &gpRTL8139_Cards[ i ];
+               gpRTL8139_Cards[ i ].Node.NumACLs = 0;
+               gpRTL8139_Cards[ i ].Node.CTime = now();
+               gpRTL8139_Cards[ i ].Node.Write = RTL8139_Write;
+               gpRTL8139_Cards[ i ].Node.Read = RTL8139_Read;
+               gpRTL8139_Cards[ i ].Node.IOCtl = RTL8139_IOCtl;
+               
+               Log_Log("RTL8139", "Card %i 0x%04x %02x:%02x:%02x:%02x:%02x:%02x",
+                       i, base,
+                       gpRTL8139_Cards[ i ].MacAddr[0], gpRTL8139_Cards[ i ].MacAddr[1],
+                       gpRTL8139_Cards[ i ].MacAddr[2], gpRTL8139_Cards[ i ].MacAddr[3],
+                       gpRTL8139_Cards[ i ].MacAddr[4], gpRTL8139_Cards[ i ].MacAddr[5]
+                       );
+               
+               i ++;
+       }
+       return MODULE_ERR_OK;
+}
index 1ba124b..0aadb6e 100644 (file)
@@ -2,7 +2,7 @@
  * Acess2 IDE Harddisk Driver
  * - main.c
  */
-#define DEBUG  1
+#define DEBUG  0
 #include <acess.h>
 #include <modules.h>
 #include <vfs.h>
@@ -76,7 +76,7 @@ void  ATA_int_BusMasterWriteByte(int Ofs, Uint8 Value);
 void   ATA_int_BusMasterWriteDWord(int Ofs, Uint32 Value);
 
 // === GLOBALS ===
-MODULE_DEFINE(0, 0x0032, i386ATA, ATA_Install, NULL, NULL);
+MODULE_DEFINE(0, 0x0032, i386ATA, ATA_Install, NULL, "PCI", NULL);
 tDevFS_Driver  gATA_DriverInfo = {
        NULL, "ata",
        {
@@ -112,16 +112,16 @@ int ATA_Install()
        int     ret;
 
        ret = ATA_SetupIO();
-       if(ret != 1)    return ret;
+       if(ret) return ret;
 
        ATA_SetupPartitions();
 
        ATA_SetupVFS();
 
        if( DevFS_AddDevice( &gATA_DriverInfo ) == 0 )
-               return MODULE_INIT_FAILURE;
+               return MODULE_ERR_MISC;
 
-       return MODULE_INIT_SUCCESS;
+       return MODULE_ERR_OK;
 }
 
 /**
@@ -141,15 +141,17 @@ int ATA_SetupIO()
        gATA_BusMasterBase = PCI_GetBAR4( ent );
        if( gATA_BusMasterBase == 0 ) {
                Warning("It seems that there is no Bus Master Controller on this machine. Get one");
-               LEAVE('i', MODULE_INIT_FAILURE);
-               return MODULE_INIT_FAILURE;
+               LEAVE('i', MODULE_ERR_NOTNEEDED);
+               return MODULE_ERR_NOTNEEDED;
        }
+       
+       // Map memory
        if( !(gATA_BusMasterBase & 1) )
        {
                if( gATA_BusMasterBase < 0x100000 )
                        gATA_BusMasterBasePtr = (void*)(0xC0000000|gATA_BusMasterBase);
                else
-                       gATA_BusMasterBasePtr = (void*)( MM_MapHWPage( gATA_BusMasterBase, 1 ) + (gATA_BusMasterBase&0xFFF) );
+                       gATA_BusMasterBasePtr = (void*)( MM_MapHWPages( gATA_BusMasterBase, 1 ) + (gATA_BusMasterBase&0xFFF) );
                LOG("gATA_BusMasterBasePtr = %p", gATA_BusMasterBasePtr);
        }
        else {
@@ -157,6 +159,7 @@ int ATA_SetupIO()
                LOG("gATA_BusMasterBase = 0x%x", gATA_BusMasterBase & ~1);
        }
 
+       // Register IRQs and get Buffers
        IRQ_AddHandler( gATA_IRQPri, ATA_IRQHandlerPri );
        IRQ_AddHandler( gATA_IRQSec, ATA_IRQHandlerSec );
 
@@ -172,11 +175,13 @@ int ATA_SetupIO()
        LOG("addr = 0x%x", addr);
        ATA_int_BusMasterWriteDWord(12, addr);
 
+       // Enable controllers
        outb(IDE_PRI_BASE+1, 1);
        outb(IDE_SEC_BASE+1, 1);
 
-       LEAVE('i', MODULE_INIT_SUCCESS);
-       return MODULE_INIT_SUCCESS;
+       // return
+       LEAVE('i', MODULE_ERR_OK);
+       return MODULE_ERR_OK;
 }
 
 /**
index 58fb824..f72e548 100644 (file)
 #define FDD_VERSION     ((0<<8)|(75))\r
 \r
 // --- Options\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
 #define MOTOR_OFF_DELAY        2000    // Miliseconds\r
+#define        FDD_MAX_READWRITE_ATTEMPTS      16\r
 \r
 // === TYPEDEFS ===\r
 /**\r
  * \brief Representation of a floppy drive\r
  */\r
-typedef struct {\r
+typedef struct sFloppyDrive\r
+{\r
         int    type;\r
        volatile int    motorState;     //2 - On, 1 - Spinup, 0 - Off\r
         int    track[2];\r
@@ -52,6 +52,9 @@ typedef struct {
 static const char      *cFDD_TYPES[] = {"None", "360kB 5.25\"", "1.2MB 5.25\"", "720kB 3.5\"", "1.44MB 3.5\"", "2.88MB 3.5\"" };\r
 static const int       cFDD_SIZES[] = { 0, 360*1024, 1200*1024, 720*1024, 1440*1024, 2880*1024 };\r
 static const short     cPORTBASE[] = { 0x3F0, 0x370 };\r
+#if DEBUG\r
+static const char      *cFDD_STATUSES[] = {NULL, "Error", "Invalid command", "Drive not ready"};\r
+#endif\r
 \r
 enum FloppyPorts {\r
        PORT_STATUSA    = 0x0,\r
@@ -82,25 +85,21 @@ enum FloppyCommands {
 // === PROTOTYPES ===\r
 // --- Filesystem\r
  int   FDD_Install(char **Arguments);\r
+void   FDD_UnloadModule();\r
+// --- VFS Methods\r
 char   *FDD_ReadDir(tVFS_Node *Node, int pos);\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
+// --- Functions for IOCache/DrvUtil\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
 // --- Helpers\r
 void   FDD_IRQHandler(int Num);\r
-void   FDD_WaitIRQ();\r
+inline void    FDD_WaitIRQ();\r
 void   FDD_SensInt(int base, Uint8 *sr0, Uint8 *cyl);\r
-inline void    FDD_AquireSpinlock();\r
-inline void    FDD_FreeSpinlock();\r
-#if USE_CACHE\r
-inline void FDD_AquireCacheSpinlock();\r
-inline void FDD_FreeCacheSpinlock();\r
-#endif\r
 void   FDD_int_SendByte(int base, char byte);\r
  int   FDD_int_GetByte(int base);\r
 void   FDD_Reset(int id);\r
@@ -112,10 +111,10 @@ void      FDD_int_StartMotor(int disk);
  int   FDD_int_GetDims(int type, int lba, int *c, int *h, int *s, int *spt);\r
 \r
 // === GLOBALS ===\r
-MODULE_DEFINE(0, FDD_VERSION, FDD, FDD_Install, NULL, NULL);\r
+MODULE_DEFINE(0, FDD_VERSION, FDD, FDD_Install, NULL, "ISADMA", NULL);\r
 t_floppyDevice gFDD_Devices[2];\r
-volatile int   fdd_inUse = 0;\r
-volatile int   fdd_irq6 = 0;\r
+tSpinlock      glFDD;\r
+volatile int   gbFDD_IrqFired = 0;\r
 tDevFS_Driver  gFDD_DriverInfo = {\r
        NULL, "fdd",\r
        {\r
@@ -128,11 +127,6 @@ tDevFS_Driver      gFDD_DriverInfo = {
        .IOCtl = FDD_IOCtl\r
        }\r
 };\r
-#if USE_CACHE\r
-int    siFDD_CacheInUse = 0;\r
-int    siFDD_SectorCacheSize = CACHE_SIZE;\r
-t_floppySector sFDD_SectorCache[CACHE_SIZE];\r
-#endif\r
 \r
 // === CODE ===\r
 /**\r
@@ -151,7 +145,11 @@ int FDD_Install(char **Arguments)
        gFDD_Devices[0].track[0] = -1;\r
        gFDD_Devices[1].track[1] = -1;\r
        \r
-       Log("[FDD ] Detected Disk 0: %s and Disk 1: %s", cFDD_TYPES[data>>4], cFDD_TYPES[data&0xF]);\r
+       Log_Log("FDD", "Detected Disk 0: %s and Disk 1: %s", cFDD_TYPES[data>>4], cFDD_TYPES[data&0xF]);\r
+       \r
+       if( data == 0 ) {\r
+               return MODULE_ERR_NOTNEEDED;\r
+       }\r
        \r
        // Clear FDD IRQ Flag\r
        FDD_SensInt(0x3F0, NULL, NULL);\r
@@ -169,7 +167,7 @@ int FDD_Install(char **Arguments)
        gFDD_Devices[0].Node.Flags = 0;\r
        gFDD_Devices[0].Node.NumACLs = 0;\r
        gFDD_Devices[0].Node.Read = FDD_ReadFS;\r
-       gFDD_Devices[0].Node.Write = NULL;//fdd_writeFS;\r
+       gFDD_Devices[0].Node.Write = NULL;//FDD_WriteFS;\r
        memcpy(&gFDD_Devices[1].Node, &gFDD_Devices[0].Node, sizeof(tVFS_Node));\r
        \r
        gFDD_Devices[1].Node.Inode = 1;\r
@@ -179,50 +177,57 @@ int FDD_Install(char **Arguments)
        gFDD_Devices[1].Node.Size = cFDD_SIZES[data & 0xF];\r
        \r
        // Create Sector Cache\r
-       #if USE_CACHE\r
-       //sFDD_SectorCache = malloc(sizeof(*sFDD_SectorCache)*CACHE_SIZE);\r
-       //siFDD_SectorCacheSize = CACHE_SIZE;\r
-       #else\r
-       if( cFDD_SIZES[data >> 4] ) {\r
+       if( cFDD_SIZES[data >> 4] )\r
+       {\r
                gFDD_Devices[0].CacheHandle = IOCache_Create(\r
                        FDD_WriteSector, 0, 512,\r
                        gFDD_Devices[0].Node.Size / (512*4)\r
                        );      // Cache is 1/4 the size of the disk\r
        }\r
-       if( cFDD_SIZES[data & 15] ) {\r
+       if( cFDD_SIZES[data & 15] )\r
+       {\r
                gFDD_Devices[1].CacheHandle = IOCache_Create(\r
                        FDD_WriteSector, 0, 512,\r
                        gFDD_Devices[1].Node.Size / (512*4)\r
                        );      // Cache is 1/4 the size of the disk\r
        }\r
-       #endif\r
        \r
        // Register with devfs\r
        DevFS_AddDevice(&gFDD_DriverInfo);\r
        \r
-       return 1;\r
+       return MODULE_ERR_OK;\r
+}\r
+\r
+/**\r
+ * \brief Prepare the module for removal\r
+ */\r
+void FDD_UnloadModule()\r
+{\r
+        int    i;\r
+       //DevFS_DelDevice( &gFDD_DriverInfo );\r
+       LOCK(&glFDD);\r
+       for(i=0;i<4;i++) {\r
+               Time_RemoveTimer(gFDD_Devices[i].timer);\r
+               FDD_int_StopMotor(i);\r
+       }\r
+       RELEASE(&glFDD);\r
+       //IRQ_Clear(6);\r
 }\r
 \r
 /**\r
  * \fn char *FDD_ReadDir(tVFS_Node *Node, int pos)\r
  * \brief Read Directory\r
  */\r
-char *FDD_ReadDir(tVFS_Node *Node, int pos)\r
+char *FDD_ReadDir(tVFS_Node *Node, int Pos)\r
 {\r
        char    name[2] = "0\0";\r
-       //Update Accessed Time\r
-       //gFDD_DrvInfo.rootNode.atime = now();\r
-       \r
-       //Check for bounds\r
-       if(pos >= 2 || pos < 0)\r
-               return NULL;\r
+\r
+       if(Pos >= 2 || Pos < 0) return NULL;\r
        \r
-       if(gFDD_Devices[pos].type == 0)\r
-               return VFS_SKIP;\r
+       if(gFDD_Devices[Pos].type == 0) return VFS_SKIP;\r
        \r
-       name[0] += pos;\r
+       name[0] += Pos;\r
        \r
-       //Return\r
        return strdup(name);\r
 }\r
 \r
@@ -295,9 +300,7 @@ int FDD_IOCtl(tVFS_Node *Node, int ID, void *Data)
 */\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    ret;\r
        \r
        ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);\r
        \r
@@ -311,78 +314,12 @@ Uint64 FDD_ReadFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
                return -1;\r
        }\r
        \r
-       disk = Node->Inode;\r
-       \r
-       // Update Accessed Time\r
-       Node->ATime = now();\r
-       \r
-       #if 0\r
-       if((Offset & 0x1FF) || (Length & 0x1FF))\r
-       {\r
-               // Un-Aligned Offset/Length\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), Length > 512-sectOff ? 512-sectOff : Length);\r
-               \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
-       \r
-               //Read Middle Sectors\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
-               }\r
-       \r
-               //Read End Sectors\r
-               if(!FDD_ReadSector(disk, startOff+i, buf))\r
-                       return 0;\r
-               memcpy(Buffer, buf, (len&0x1FF)-sectOff);\r
-               
-               LEAVE('X', Length);\r
-               return Length;\r
-       }\r
-       else\r
-       {\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
-               {\r
-                       FDD_ReadSector(disk, sector, buf);\r
-                       memcpy(buffer, buf, 512);\r
-                       buffer += 512;\r
-                       sector++;\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
+       ret = DrvUtil_ReadBlock(Offset, Length, Buffer, FDD_ReadSectors, 512, Node->Inode);\r
+       LEAVE('i', ret);\r
+       return ret;\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
@@ -406,140 +343,195 @@ Uint FDD_ReadSectors(Uint64 SectorAddr, Uint Count, void *Buffer, Uint Disk)
        return ret;\r
 }\r
 \r
-/**\r
- * \fn int FDD_ReadSector(Uint32 Disk, Uint64 SectorAddr, void *Buffer)\r
- * \brief Read a sector from disk\r
- * \todo Make real-hardware safe (account for read errors)\r
-*/\r
-int FDD_ReadSector(Uint32 Disk, Uint64 SectorAddr, void *Buffer)\r
+int FDD_int_ReadWriteSector(Uint32 Disk, Uint64 SectorAddr, int Write, void *Buffer)\r
 {\r
         int    cyl, head, sec;\r
         int    spt, base;\r
         int    i;\r
         int    lba = SectorAddr;\r
+       Uint8   st0, st1, st2, rcy, rhe, rse, bps;      //      Status Values\r
        \r
-       ENTER("idisk Xlba pbuf", disk, lba, buf);\r
+       ENTER("iDisk XSectorAddr pBuffer", Disk, SectorAddr, Buffer);\r
        \r
-       #if USE_CACHE\r
-       FDD_AquireCacheSpinlock();\r
-       for( i = 0; i < siFDD_SectorCacheSize; i++ )\r
-       {\r
-               if(sFDD_SectorCache[i].timestamp == 0)  continue;\r
-               if(sFDD_SectorCache[i].disk == Disk\r
-               && sFDD_SectorCache[i].sector == lba) {\r
-                       LOG("Found %i in cache %i", lba, i);\r
-                       memcpy(Buffer, sFDD_SectorCache[i].data, 512);\r
-                       sFDD_SectorCache[i].timestamp = now();\r
-                       FDD_FreeCacheSpinlock();\r
-                       LEAVE('i', 1);\r
-                       return 1;\r
-               }\r
-       }\r
-       LOG("Read %i from Disk", lba);\r
-       FDD_FreeCacheSpinlock();\r
-       #else\r
-       if( IOCache_Read( gFDD_Devices[Disk].CacheHandle, SectorAddr, Buffer ) == 1 ) {\r
-               LEAVE('i', 1);\r
-               return 1;\r
-       }\r
-       #endif\r
-       \r
-       base = cPORTBASE[Disk>>1];\r
+       base = cPORTBASE[Disk >> 1];\r
        \r
        LOG("Calculating Disk Dimensions");\r
        // Get CHS position\r
-       if(FDD_int_GetDims(gFDD_Devices[Disk].type, lba, &cyl, &head, &sec, &spt) != 1) {\r
+       if(FDD_int_GetDims(gFDD_Devices[Disk].type, lba, &cyl, &head, &sec, &spt) != 1)\r
+       {\r
                LEAVE('i', -1);\r
                return -1;\r
        }\r
+       LOG("Cyl=%i, Head=%i, Sector=%i", cyl, head, sec);\r
        \r
-       // Remove Old Timer\r
-       Time_RemoveTimer(gFDD_Devices[Disk].timer);\r
-       // Check if Motor is on\r
-       if(gFDD_Devices[Disk].motorState == 0) {\r
-               FDD_int_StartMotor(Disk);\r
-       }\r
+       LOCK(&glFDD);   // Lock to stop the motor stopping on us\r
+       Time_RemoveTimer(gFDD_Devices[Disk].timer);     // Remove Old Timer\r
+       // Start motor if needed\r
+       if(gFDD_Devices[Disk].motorState != 2)  FDD_int_StartMotor(Disk);\r
+       RELEASE(&glFDD);\r
        \r
-       LOG("Wait for Motor Spinup");\r
+       LOG("Wait for the motor to spin up");\r
        \r
        // Wait for spinup\r
        while(gFDD_Devices[Disk].motorState == 1)       Threads_Yield();\r
        \r
-       LOG("C:%i,H:%i,S:%i", cyl, head, sec);\r
        LOG("Acquire Spinlock");\r
-       \r
-       FDD_AquireSpinlock();\r
+       LOCK(&glFDD);\r
        \r
        // Seek to track\r
-       outb(base+CALIBRATE_DRIVE, 0);\r
+       outb(base + CALIBRATE_DRIVE, 0);\r
        i = 0;\r
-       while(FDD_int_SeekTrack(Disk, head, (Uint8)cyl) == 0 && i++ < FDD_SEEK_TIMEOUT )        Threads_Yield();\r
+       while(FDD_int_SeekTrack(Disk, head, (Uint8)cyl) == 0 && i++ < FDD_SEEK_TIMEOUT )\r
+               Threads_Yield();\r
+       if( i > FDD_SEEK_TIMEOUT ) {\r
+               RELEASE(&glFDD);\r
+               LEAVE('i', 0);\r
+               return 0;\r
+       }\r
        //FDD_SensInt(base, NULL, NULL);        // Wait for IRQ\r
-       \r
+               \r
+       // Read Data from DMA\r
        LOG("Setting DMA for read");\r
+       DMA_SetChannel(2, 512, !Write); // Read 512 Bytes from channel 2\r
        \r
-       //Read Data from DMA\r
-       DMA_SetChannel(2, 512, 1);      // Read 512 Bytes\r
-       \r
-       LOG("Sending read command");\r
+       LOG("Sending command");\r
        \r
        //Threads_Wait(100);    // Wait for Head to settle\r
        Time_Delay(100);\r
-       FDD_int_SendByte(base, READ_SECTOR);    // Was 0xE6\r
-       FDD_int_SendByte(base, (head << 2) | (Disk&1));\r
-       FDD_int_SendByte(base, (Uint8)cyl);\r
-       FDD_int_SendByte(base, (Uint8)head);\r
-       FDD_int_SendByte(base, (Uint8)sec);\r
-       FDD_int_SendByte(base, 0x02);   // Bytes Per Sector (Real BPS=128*2^{val})\r
-       FDD_int_SendByte(base, spt);    // SPT\r
-       FDD_int_SendByte(base, 0x1B);   // Gap Length (27 is default)\r
-       FDD_int_SendByte(base, 0xFF);   // Data Length\r
        \r
-       // Wait for IRQ\r
-       LOG("Waiting for Data to be read");\r
-       FDD_WaitIRQ();\r
+       for( i = 0; i < FDD_MAX_READWRITE_ATTEMPTS; i ++ )\r
+       {\r
+               if( Write )\r
+                       FDD_int_SendByte(base, READ_SECTOR);    // Was 0xE6\r
+               else\r
+                       FDD_int_SendByte(base, READ_SECTOR);    // Was 0xE6\r
+               FDD_int_SendByte(base, (head << 2) | (Disk&1));\r
+               FDD_int_SendByte(base, (Uint8)cyl);\r
+               FDD_int_SendByte(base, (Uint8)head);\r
+               FDD_int_SendByte(base, (Uint8)sec);\r
+               FDD_int_SendByte(base, 0x02);   // Bytes Per Sector (Real BPS=128*2^{val})\r
+               FDD_int_SendByte(base, spt);    // SPT\r
+               FDD_int_SendByte(base, 0x1B);   // Gap Length (27 is default)\r
+               FDD_int_SendByte(base, 0xFF);   // Data Length\r
+               \r
+               // Wait for IRQ\r
+               if( Write ) {\r
+                       LOG("Writing Data");\r
+                       DMA_WriteData(2, 512, Buffer);\r
+                       LOG("Waiting for Data to be written");\r
+                       FDD_WaitIRQ();\r
+               }\r
+               else {\r
+                       LOG("Waiting for data to be read");\r
+                       FDD_WaitIRQ();\r
+                       LOG("Reading Data");\r
+                       DMA_ReadData(2, 512, Buffer);\r
+               }\r
+               \r
+               // Clear Input Buffer\r
+               LOG("Clearing Input Buffer");\r
+               // Status Values\r
+               st0 = FDD_int_GetByte(base);\r
+               st1 = FDD_int_GetByte(base);\r
+               st2 = FDD_int_GetByte(base);\r
+               \r
+               // Cylinder, Head and Sector (mutilated in some way\r
+               rcy = FDD_int_GetByte(base);\r
+               rhe = FDD_int_GetByte(base);\r
+               rse = FDD_int_GetByte(base);\r
+               // Should be the BPS set above (0x02)\r
+               bps = FDD_int_GetByte(base);\r
+               \r
+               // Check Status\r
+               // - Error Code\r
+               if(st0 & 0xC0) {\r
+                       LOG("Error (st0 & 0xC0) \"%s\"", cFDD_STATUSES[st0 >> 6]);\r
+                       continue;\r
+        }\r
+        // - Status Flags\r
+        if(st0 & 0x08) {       LOG("Drive not ready"); continue;       }\r
+        if(st1 & 0x80) {       LOG("End of Cylinder"); continue;       }\r
+               if(st1 & 0x20) {        LOG("CRC Error");       continue;       }\r
+               if(st1 & 0x10) {        LOG("Controller Timeout");      continue;       }\r
+               if(st1 & 0x04) {        LOG("No Data Found");   continue;       }\r
+               if(st1 & 0x01 || st2 & 0x01) {\r
+                       LOG("No Address mark found");\r
+                       continue;\r
+               }\r
+        if(st2 & 0x40) {       LOG("Deleted address mark");    continue;       }\r
+               if(st2 & 0x20) {        LOG("CRC error in data");       continue;       }\r
+               if(st2 & 0x10) {        LOG("Wrong Cylinder");  continue;       }\r
+               if(st2 & 0x04) {        LOG("uPD765 sector not found"); continue;       }\r
+               if(st2 & 0x02) {        LOG("Bad Cylinder");    continue;       }\r
+               \r
+               if(bps != 0x2) {\r
+                       LOG("Returned BPS = 0x%02x, not 0x02", bps);\r
+                       continue;\r
+               }\r
+               \r
+               if(st1 & 0x02) {\r
+                       LOG("Floppy not writable");\r
+                       i = FDD_MAX_READWRITE_ATTEMPTS+1;\r
+                       break;\r
+               }\r
+               \r
+               // Success!\r
+               break;\r
+       }\r
        \r
-       // Read Data from DMA\r
-       LOG(" FDD_ReadSector: Reading Data");\r
-       DMA_ReadData(2, 512, Buffer);\r
+       // Release Spinlock\r
+       LOG("Realeasing Spinlock and setting motor to stop");\r
+       RELEASE(&glFDD);\r
+       \r
+       if(i == FDD_MAX_READWRITE_ATTEMPTS) {\r
+               Log_Warning("FDD", "Exceeded %i attempts in %s the disk",\r
+                       FDD_MAX_READWRITE_ATTEMPTS,\r
+                       (Write ? "writing to" : "reading from")\r
+                       );\r
+       }\r
        \r
-       // Clear Input Buffer\r
-       LOG("Clearing Input Buffer");\r
-       FDD_int_GetByte(base); FDD_int_GetByte(base); FDD_int_GetByte(base);\r
-       FDD_int_GetByte(base); FDD_int_GetByte(base); FDD_int_GetByte(base); FDD_int_GetByte(base);\r
+       // Don't turn the motor off now, wait for a while\r
+       gFDD_Devices[Disk].timer = Time_CreateTimer(MOTOR_OFF_DELAY, FDD_int_StopMotor, (void*)Disk);\r
+\r
+       if( i < FDD_MAX_READWRITE_ATTEMPTS ) {\r
+               LEAVE('i', 0);\r
+               return 0;\r
+       }\r
+       else {\r
+               LEAVE('i', 1);\r
+               return 1;\r
+       }\r
+}\r
+\r
+/**\r
+ * \fn int FDD_ReadSector(Uint32 Disk, Uint64 SectorAddr, void *Buffer)\r
+ * \brief Read a sector from disk\r
+ * \todo Make real-hardware safe (account for read errors)\r
+*/\r
+int FDD_ReadSector(Uint32 Disk, Uint64 SectorAddr, void *Buffer)\r
+{\r
+        int    ret;\r
        \r
-       LOG("Realeasing Spinlock and Setting motor to stop");\r
-       // Release Spinlock\r
-       FDD_FreeSpinlock();\r
+       ENTER("iDisk XSectorAddr pBuffer", Disk, SectorAddr, Buffer);\r
        \r
-       //Set timer to turn off motor affter a gap\r
-       gFDD_Devices[Disk].timer = Time_CreateTimer(MOTOR_OFF_DELAY, FDD_int_StopMotor, (void*)Disk);   //One Shot Timer
+       if( IOCache_Read( gFDD_Devices[Disk].CacheHandle, SectorAddr, Buffer ) == 1 ) {\r
+               LEAVE('i', 1);\r
+               return 1;\r
+       }\r
+       \r
+       // Pass to general function\r
+       ret = FDD_int_ReadWriteSector(Disk, SectorAddr, 0, Buffer);
 \r
-       #if USE_CACHE\r
-       {\r
-               FDD_AquireCacheSpinlock();\r
-               int oldest = 0;\r
-               for(i=0;i<siFDD_SectorCacheSize;i++)\r
-               {\r
-                       if(sFDD_SectorCache[i].timestamp == 0) {\r
-                               oldest = i;\r
-                               break;\r
-                       }\r
-                       if(sFDD_SectorCache[i].timestamp < sFDD_SectorCache[oldest].timestamp)\r
-                               oldest = i;\r
-               }\r
-               sFDD_SectorCache[oldest].timestamp = now();\r
-               sFDD_SectorCache[oldest].disk = Disk;\r
-               sFDD_SectorCache[oldest].sector = lba;\r
-               memcpy(sFDD_SectorCache[oldest].data, Buffer, 512);\r
-               FDD_FreeCacheSpinlock();\r
+       if( ret == 0 ) {\r
+               IOCache_Add( gFDD_Devices[Disk].CacheHandle, SectorAddr, Buffer );
+               LEAVE('i', 1);\r
+               return 1;\r
+       }\r
+       else {\r
+               LOG("Reading failed");\r
+               LEAVE('i', 0);\r
+               return 0;\r
        }\r
-       #else\r
-       IOCache_Add( gFDD_Devices[Disk].CacheHandle, SectorAddr, Buffer );\r
-       #endif\r
-
-       LEAVE('i', 1);\r
-       return 1;\r
 }\r
 \r
 /**\r
@@ -648,18 +640,18 @@ int FDD_int_GetDims(int type, int lba, int *c, int *h, int *s, int *spt)
  */\r
 void FDD_IRQHandler(int Num)\r
 {\r
-    fdd_irq6 = 1;\r
+    gbFDD_IrqFired = 1;\r
 }\r
 \r
 /**\r
  * \fn FDD_WaitIRQ()\r
  * \brief Wait for an IRQ6\r
  */\r
-void FDD_WaitIRQ()\r
+inline void FDD_WaitIRQ()\r
 {\r
        // Wait for IRQ\r
-       while(!fdd_irq6)        Threads_Yield();\r
-       fdd_irq6 = 0;\r
+       while(!gbFDD_IrqFired)  Threads_Yield();\r
+       gbFDD_IrqFired = 0;\r
 }\r
 \r
 void FDD_SensInt(int base, Uint8 *sr0, Uint8 *cyl)\r
@@ -671,30 +663,6 @@ void FDD_SensInt(int base, Uint8 *sr0, Uint8 *cyl)
        else    FDD_int_GetByte(base);\r
 }\r
 \r
-void FDD_AquireSpinlock()\r
-{\r
-       while(fdd_inUse)\r
-               Threads_Yield();\r
-       fdd_inUse = 1;\r
-}\r
-\r
-inline void FDD_FreeSpinlock()\r
-{\r
-       fdd_inUse = 0;\r
-}\r
-\r
-#if USE_CACHE\r
-inline void FDD_AquireCacheSpinlock()\r
-{\r
-       while(siFDD_CacheInUse) Threads_Yield();\r
-       siFDD_CacheInUse = 1;\r
-}\r
-inline void FDD_FreeCacheSpinlock()\r
-{\r
-       siFDD_CacheInUse = 0;\r
-}\r
-#endif\r
-\r
 /**\r
  * void FDD_int_SendByte(int base, char byte)\r
  * \brief Sends a command to the controller\r
@@ -713,8 +681,9 @@ void FDD_int_SendByte(int base, char byte)
         }\r
         inb(0x80);     //Delay\r
     }\r
+       \r
        #if WARN\r
-               Warning("FDD_int_SendByte - Timeout sending byte 0x%x to base 0x%x\n", byte, base);\r
+       Warning("FDD_int_SendByte - Timeout sending byte 0x%x to base 0x%x\n", byte, base);\r
        #endif\r
 }\r
 \r
@@ -828,23 +797,12 @@ void FDD_int_StartMotor(int disk)
 void FDD_int_StopMotor(int disk)\r
 {\r
        Uint8   state;\r
+       if( IS_LOCKED(&glFDD) ) return ;\r
+       ENTER("iDisk", disk);\r
+       \r
        state = inb( cPORTBASE[ disk>>1 ] + PORT_DIGOUTPUT );\r
        state &= ~( 1 << (4+disk) );\r
        outb( cPORTBASE[ disk>>1 ] + PORT_DIGOUTPUT, state );\r
     gFDD_Devices[disk].motorState = 0;\r
-}\r
-\r
-/**\r
- * \fn void ModuleUnload()\r
- * \brief Prepare the module for removal\r
- */\r
-void ModuleUnload()\r
-{\r
-       int i;\r
-       FDD_AquireSpinlock();\r
-       for(i=0;i<4;i++) {\r
-               Time_RemoveTimer(gFDD_Devices[i].timer);\r
-               FDD_int_StopMotor(i);\r
-       }\r
-       //IRQ_Clear(6);\r
+    LEAVE('-');\r
 }\r
index 80c6d4d..d5291f6 100644 (file)
@@ -1 +1,3 @@
+CATEGORY = Storage
+
 -include ../../Makefile.tpl
diff --git a/Modules/USB/Core/Makefile b/Modules/USB/Core/Makefile
new file mode 100644 (file)
index 0000000..af92731
--- /dev/null
@@ -0,0 +1,7 @@
+#
+#
+
+OBJ = main.o uhci.o
+NAME = Core
+
+-include ../Makefile.tpl
diff --git a/Modules/USB/Core/main.c b/Modules/USB/Core/main.c
new file mode 100644 (file)
index 0000000..5744c29
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Acess2
+ * USB Stack
+ */
+#define VERSION        ( (0<<8)| 5 )
+#define DEBUG  1
+#include <acess.h>
+#include <vfs.h>
+#include <fs_devfs.h>
+#include <modules.h>
+#include "usb.h"
+
+// === IMPORTS ===
+ int   UHCI_Initialise();
+
+// === PROTOTYPES ===
+ int   USB_Install(char **Arguments);
+void   USB_Cleanup();
+char   *USB_ReadDir(tVFS_Node *Node, int Pos);
+tVFS_Node      *USB_FindDir(tVFS_Node *Node, char *Name);
+ int   USB_IOCtl(tVFS_Node *Node, int Id, void *Data);
+
+// === GLOBALS ===
+MODULE_DEFINE(0, VERSION, USB, USB_Install, NULL, NULL);
+tDevFS_Driver  gUSB_DrvInfo = {
+       NULL, "usb", {
+               .NumACLs = 1,
+               .ACLs = &gVFS_ACL_EveryoneRX,
+               .Flags = VFS_FFLAG_DIRECTORY,
+               .ReadDir = USB_ReadDir,
+               .FindDir = USB_FindDir,
+               .IOCtl = USB_IOCtl
+       }
+};
+tUSBDevice     *gUSB_Devices = NULL;
+tUSBHost       *gUSB_Hosts = NULL;
+
+// === CODE ===
+/**
+ * \fn int ModuleLoad()
+ * \brief Called once module is loaded
+ */
+int USB_Install(char **Arguments)
+{
+       UHCI_Initialise();
+       Warning("[USB  ] Not Complete - Devel Only");
+       return MODULE_ERR_OK;
+}
+
+/**
+ * \fn void USB_Cleanup()
+ * \brief Called just before module is unloaded
+ */
+void USB_Cleanup()
+{
+}
+
+/**
+ * \fn char *USB_ReadDir(tVFS_Node *Node, int Pos)
+ * \brief Read from the USB root
+ */
+char *USB_ReadDir(tVFS_Node *Node, int Pos)
+{
+       return NULL;
+}
+
+/**
+ * \fn tVFS_Node *USB_FindDir(tVFS_Node *Node, char *Name)
+ * \brief Locate an entry in the USB root
+ */
+tVFS_Node *USB_FindDir(tVFS_Node *Node, char *Name)
+{
+       return NULL;
+}
+
+/**
+ * \brief Handles IOCtl Calls to the USB driver
+ */
+int USB_IOCtl(tVFS_Node *Node, int Id, void *Data)
+{
+       return 0;
+}
diff --git a/Modules/USB/Core/uhci.c b/Modules/USB/Core/uhci.c
new file mode 100644 (file)
index 0000000..e8cb7b7
--- /dev/null
@@ -0,0 +1,120 @@
+/*\r
+ * Acess 2 USB Stack\r
+ * Universal Host Controller Interface\r
+ */\r
+#define DEBUG  1\r
+#include <acess.h>\r
+#include <vfs.h>\r
+#include <drv_pci.h>\r
+#include "usb.h"\r
+#include "uhci.h"\r
+\r
+// === CONSTANTS ===\r
+#define        MAX_CONTROLLERS 4\r
+#define NUM_TDs        1024\r
+\r
+// === PROTOTYPES ===\r
+ int   UHCI_Initialise();\r
+void   UHCI_Cleanup();\r
+ int   UHCI_IOCtl(tVFS_Node *node, int id, void *data);\r
+ int   UHCI_Int_InitHost(tUHCI_Controller *Host);\r
+\r
+// === GLOBALS ===
+//Uint gaFrameList[1024];\r
+tUHCI_TD       gaUHCI_TDPool[NUM_TDs];\r
+tUHCI_Controller       gUHCI_Controllers[MAX_CONTROLLERS];\r
+\r
+// === CODE ===\r
+/**\r
+ * \fn int UHCI_Initialise()\r
+ * \brief Called to initialise the UHCI Driver\r
+ */\r
+int UHCI_Initialise()\r
+{\r
+        int    i=0, id=-1;\r
+        int    ret;\r
+       Uint16  base;\r
+       \r
+       ENTER("");\r
+       \r
+       // Enumerate PCI Bus, getting a maximum of `MAX_CONTROLLERS` devices\r
+       while( (id = PCI_GetDeviceByClass(0x0C03, 0xFFFF, id)) >= 0 && i < MAX_CONTROLLERS )\r
+       {\r
+               gUHCI_Controllers[i].PciId = id;\r
+               // Assign a port range (BAR4, Reserve 32 ports)\r
+               base = PCI_AssignPort( id, 4, 0x20 );\r
+               gUHCI_Controllers[i].IOBase = base;\r
+               \r
+               Log("[USB  ] Controller PCI #%i: IO Base = 0x%x", id, base);\r
+               \r
+               // Initialise Host\r
+               ret = UHCI_Int_InitHost(&gUHCI_Controllers[i]);\r
+               // Detect an error\r
+               if(ret != 0) {\r
+                       LEAVE('i', ret);\r
+                       return ret;\r
+               }\r
+               \r
+               i ++;\r
+       }\r
+       if(i == MAX_CONTROLLERS) {\r
+               Warning("[UHCI ] Over "EXPAND_STR(MAX_CONTROLLERS)" UHCI controllers detected, ignoring rest");\r
+       }\r
+       LEAVE('i', i);\r
+       return i;\r
+}\r
+\r
+/**\r
+ * \fn void UHCI_Cleanup()\r
+ * \brief Called just before module is unloaded\r
+ */\r
+void UHCI_Cleanup()\r
+{\r
+}
+\r
+/**\r
+ * \brief Sends a packet to a device endpoint\r
+ */\r
+int UHCI_SendPacket(int ControllerId, int Length)\r
+{\r
+       //tUHCI_TD      *td = UHCI_AllocateTD();\r
+       return 0;\r
+}\r
+\r
+// === INTERNAL FUNCTIONS ===\r
+/**\r
+ * \fn int UHCI_Int_InitHost(tUCHI_Controller *Host)\r
+ * \brief Initialises a UHCI host controller\r
+ * \param Host Pointer - Host to initialise\r
+ */\r
+int UHCI_Int_InitHost(tUHCI_Controller *Host)\r
+{\r
+       ENTER("pHost", Host);\r
+       \r
+       // Allocate Frame List\r
+       Host->FrameList = (void *) MM_AllocDMA(1, 32, &Host->PhysFrameList);    // 1 Page, 32-bit\r
+       if( !Host->FrameList ) {\r
+               Warning("[UHCI ] Unable to allocate frame list, aborting");\r
+               LEAVE('i', -1);\r
+               return -1;\r
+       }\r
+       LOG("Allocated frame list 0x%x (0x%x)", Host->FrameList, Host->PhysFrameList);\r
+       memsetd( Host->FrameList, 1, 1024 );    // Clear List (Disabling all entries)\r
+       \r
+       //! \todo Properly fill frame list\r
+       \r
+       // Set frame length to 1 ms\r
+       outb( Host->IOBase + SOFMOD, 64 );\r
+       \r
+       // Set Frame List Address\r
+       outd( Host->IOBase + FLBASEADD, Host->PhysFrameList );\r
+       \r
+       // Set Frame Number\r
+       outw( Host->IOBase + FRNUM, 0 );\r
+       \r
+       // Enable Interrupts\r
+       //PCI_WriteWord( Host->PciId, 0xC0, 0x2000 );\r
+       \r
+       LEAVE('i', 0);\r
+       return 0;\r
+}\r
diff --git a/Modules/USB/Core/uhci.h b/Modules/USB/Core/uhci.h
new file mode 100644 (file)
index 0000000..df7854b
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ * AcessOS Version 1
+ * USB Stack
+ * - Universal Host Controller Interface
+ */
+#ifndef _UHCI_H_
+#define _UHCI_H_
+
+// === TYPES ===
+typedef struct sUHCI_Controller        tUHCI_Controller;
+typedef struct sUHCI_TD        tUHCI_TD;
+typedef struct sUHCI_QH        tUHCI_QH;
+
+// === STRUCTURES ===
+struct sUHCI_Controller
+{
+       /**
+        * \brief PCI Device ID
+        */
+       Uint16  PciId;
+       
+       /**
+        * \brief IO Base Address
+        */
+       Uint16  IOBase;
+       
+       /**
+        * \brief Frame list
+        * 
+        * 31:4 - Frame Pointer
+        * 3:2 - Reserved
+        * 1 - QH/TD Selector
+        * 0 - Terminate (Empty Pointer)
+        */
+       Uint32  *FrameList;
+       
+       /**
+        * \brief Physical Address of the Frame List
+        */
+       tPAddr  PhysFrameList;
+};
+
+struct sUHCI_TD
+{
+       /**
+        * \brief Next Entry in list
+        * 
+        * 31:4 - Address
+        * 3 - Reserved
+        * 2 - Depth/Breadth Select
+        * 1 - QH/TD Select
+        * 0 - Terminate (Last in List)
+        */
+       Uint32  Link;
+       
+       /**
+        * \brief Control and Status Field
+        * 
+        * 31:30 - Reserved
+        * 29 - Short Packet Detect (Input Only)
+        * 28:27 - Number of Errors Allowed
+        * 26 - Low Speed Device (Communicating with a low speed device)
+        * 25 - Isynchonious Select
+        * 24 - Interrupt on Completion (IOC)
+        * 23:16 - Status
+        *     23 - Active
+        *     22 - Stalled
+        *     21 - Data Buffer Error
+        *     20 - Babble Detected
+        *     19 - NAK Detected
+        *     18 - CRC/Timout Error
+        *     17 - Bitstuff Error
+        *     16 - Reserved
+        * 15:11 - Reserved
+        * 10:0 - Actual Length (Number of bytes transfered)
+        */
+       Uint32  Control;
+       
+       /**
+        * \brief Packet Header
+        * 
+        * 31:21 - Maximum Length (0=1, Max 0x4FF, 0x7FF=0)
+        * 20 - Reserved
+        * 19 - Data Toggle
+        * 18:15 - Endpoint
+        * 14:8 - Device Address
+        * 7:0 - PID (Packet Identifcation) - Only 96, E1, 2D allowed
+        */
+       Uint32  Token;
+       
+       /**
+        * \brief Pointer to the data to send
+        */
+       Uint32  BufferPointer;
+};
+
+struct sUHCI_QH
+{
+       /**
+        * \brief Next Entry in list
+        * 
+        * 31:4 - Address
+        * 3:2 - Reserved
+        * 1 - QH/TD Select
+        * 0 - Terminate (Last in List)
+        */
+       Uint32  Next;
+
+       
+       /**
+        * \brief Next Entry in list
+        * 
+        * 31:4 - Address
+        * 3:2 - Reserved
+        * 1 - QH/TD Select
+        * 0 - Terminate (Last in List)
+        */
+       Uint32  Child;
+};
+
+// === ENUMERATIONS ===
+enum eUHCI_IOPorts {
+       /**
+        * \brief USB Command Register
+        * 
+        * 15:8 - Reserved
+        * 7 - Maximum Packet Size selector (1: 64 bytes, 0: 32 bytes)
+        * 6 - Configure Flag (No Hardware Effect)
+        * 5 - Software Debug (Don't think it will be needed)
+        * 4 - Force Global Resume
+        * 3 - Enter Global Suspend Mode
+        * 2 - Global Reset (Resets all devices on the bus)
+        * 1 - Host Controller Reset (Reset just the controller)
+        * 0 - Run/Stop
+        */
+       USBCMD  = 0x00,
+       /**
+        * \brief USB Status Register
+        * 
+        * 15:6 - Reserved
+        * 5 - HC Halted, set to 1 when USBCMD:RS is set to 0
+        * 4 - Host Controller Process Error (Errors related to the bus)
+        * 3 - Host System Error (Errors related to the OS/PCI Bus)
+        * 2 - Resume Detect (Set if a RESUME command is sent to the Controller)
+        * 1 - USB Error Interrupt
+        * 0 - USB Interrupts (Set if a transaction with the IOC bit set is completed)
+        */
+       USBSTS  = 0x02,
+       /**
+        * \brief USB Interrupt Enable Register
+        * 
+        * 15:4 - Reserved
+        * 3 - Short Packet Interrupt Enable
+        * 2 - Interrupt on Complete (IOC) Enable
+        * 1 - Resume Interrupt Enable
+        * 0 - Timout / CRC Error Interrupt Enable
+        */
+       USBINTR = 0x04,
+       /**
+        * \brief Frame Number (Index into the Frame List)
+        * 
+        * 15:11 - Reserved
+        * 10:0 - Index (Incremented each approx 1ms)
+        */
+       FRNUM   = 0x06,
+       /**
+        * \brief Frame List Base Address
+        * 
+        * 31:12 - Pysical Address >> 12
+        * 11:0 - Reserved (Set to Zero)
+        */
+       FLBASEADD = 0x08,       // 32-bit
+       /**
+        * \brief Start-of-frame Modify Register
+        * \note 8-bits only
+        * 
+        * Sets the size of a frame
+        * Frequency = (11936+n)/12000 kHz
+        * 
+        * 7 - Reserved
+        * 6:0 -
+        */
+       SOFMOD = 0x0C,  // 8bit
+       /**
+        * \brief Port Status and Controll Register (Port 1)
+        * 
+        * 15:13 - Reserved
+        * 12 - Suspend
+        * 11:10 - Reserved
+        * 9 - Port Reset
+        * 8 - Low Speed Device Attached
+        * 5:4 - Line Status
+        * 3 - Port Enable/Disable Change - Used for detecting device removal
+        * 2 - Port Enable/Disable
+        * 1 - Connect Status Change
+        * 0 - Current Connect Status
+        */
+       PORTSC1 = 0x10,
+       /**
+        * \brief Port Status and Controll Register (Port 2)
+        * 
+        * See ::PORTSC1
+        */
+       PORTSC2 = 0x12
+};
+
+#endif
diff --git a/Modules/USB/Core/usb.c b/Modules/USB/Core/usb.c
new file mode 100644 (file)
index 0000000..60bf3f2
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Acess 2 USB Stack
+ * USB Packet Control
+ */
+#define DEBUG  1
+#include <acess.h>
+#include <vfs.h>
+#include <drv_pci.h>
+#include "usb.h"
+
+
+// === CODE ===
+void USB_MakeToken(void *Buf, int PID, int Addr, int EndP)
+{
+       Uint8   *tok = Buf;
+        int    crc = 0;
+       
+       tok[0] = PID & 0xFF;
+       tok[1] = (Addr & 0x7F) | ((EndP&1)<<7);
+       tok[2] = ((EndP >> 1) & 0x7) | crc;
+}
+
+#if 0
+void USB_SendData(int Controller, int Dev, int Endpoint, void *Data, int Length)
+{
+       Uint8   buf[Length+3+2/*?*/];
+       
+       USB_MakeToken(buf, PID_DATA0, Dev, Endpoint);
+       
+       switch(Controller & 0xF00)
+       {
+       case 1: // UHCI
+               UHCI_SendPacket(Controller & 0xFF);
+               break;
+       }
+}
+#endif
diff --git a/Modules/USB/Core/usb.h b/Modules/USB/Core/usb.h
new file mode 100644 (file)
index 0000000..397e4d7
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * AcessOS Version 1
+ * USB Stack
+ */
+#ifndef _USB_H_
+#define _USB_H_
+
+// === TYPES ===
+typedef struct sUSBHost        tUSBHost;
+typedef struct sUSBDevice      tUSBDevice;
+
+// === CONSTANTS ===
+enum eUSB_PIDs
+{
+       /**
+        * \name Token
+        * \{
+        */
+       PID_OUT         = 0xE1,
+       PID_IN          = 0x69,
+       PID_SOF         = 0xA5,
+       PID_SETUP       = 0x2D,
+       /**
+        * \}
+        */
+       
+       /**
+        * \name Data
+        * \{
+        */
+       PID_DATA0       = 0xC3,
+       PID_DATA1       = 0x4B,
+       PID_DATA2       = 0x87, // USB2 only
+       PID_MDATA       = 0x0F, // USB2 only
+       /**
+        * \}
+        */
+       
+       /**
+        * \name Handshake
+        * \{
+        */
+       PID_ACK         = 0xD2,
+       PID_NAK         = 0x5A,
+       PID_STALL       = 0x1E,
+       PID_NYET        = 0x96,
+       /**
+        * \}
+        */
+       
+       /**
+        * \name Special
+        * \{
+        */
+       PID_PRE         = 0x3C, PID_ERR         = 0x3C,
+       PID_SPLIT       = 0x78,
+       PID_PING        = 0xB4,
+       PID_RESVD       = 0xF0,
+       /**
+        * \}
+        */
+};
+
+// === FUNCTIONS ===
+/**
+ * \note 00101 - X^5+X^2+1
+ */
+Uint8  USB_TokenCRC(void *Data, int len);
+/**
+ * \note X^16 + X15 + X^2 + 1
+ */
+Uint16 USB_DataCRC(void *Data, int len);
+
+// === STRUCTURES ===
+/**
+ * \brief Defines a USB Host Controller
+ */
+struct sUSBHost
+{
+       Uint16  IOBase;
+       
+        int    (*SendPacket)(int ID, int Length, void *Data);
+};
+
+/**
+ * \brief Defines a single device on the USB Bus
+ */
+struct sUSBDevice
+{
+       tUSBHost        *Host;
+        int    MaxControl;
+        int    MaxBulk;
+        int    MaxISync;
+};
+
+#endif
diff --git a/Modules/USB/Makefile b/Modules/USB/Makefile
deleted file mode 100644 (file)
index b4f400a..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#
-#
-
-OBJ = main.o uhci.o
-NAME = USB
-
--include ../Makefile.tpl
diff --git a/Modules/USB/Makefile.tpl b/Modules/USB/Makefile.tpl
new file mode 100644 (file)
index 0000000..8df7098
--- /dev/null
@@ -0,0 +1,3 @@
+CATEGORY = USB
+
+-include ../../Makefile.tpl
diff --git a/Modules/USB/main.c b/Modules/USB/main.c
deleted file mode 100644 (file)
index 28ce5e3..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Acess2
- * USB Stack
- */
-#define VERSION        ( (0<<8)| 5 )
-#define DEBUG  1
-#include <acess.h>
-#include <vfs.h>
-#include <fs_devfs.h>
-#include <modules.h>
-#include "usb.h"
-
-// === IMPORTS ===
- int   UHCI_Initialise();
-
-// === PROTOTYPES ===
- int   USB_Install(char **Arguments);
-void   USB_Cleanup();
-char   *USB_ReadDir(tVFS_Node *Node, int Pos);
-tVFS_Node      *USB_FindDir(tVFS_Node *Node, char *Name);
- int   USB_IOCtl(tVFS_Node *Node, int Id, void *Data);
-
-// === GLOBALS ===
-MODULE_DEFINE(0, VERSION, USB, USB_Install, NULL, NULL);
-tDevFS_Driver  gUSB_DrvInfo = {
-       NULL, "usb", {
-               .NumACLs = 1,
-               .ACLs = &gVFS_ACL_EveryoneRX,
-               .Flags = VFS_FFLAG_DIRECTORY,
-               .ReadDir = USB_ReadDir,
-               .FindDir = USB_FindDir,
-               .IOCtl = USB_IOCtl
-       }
-};
-tUSBDevice     *gUSB_Devices = NULL;
-tUSBHost       *gUSB_Hosts = NULL;
-
-// === CODE ===
-/**
- * \fn int ModuleLoad()
- * \brief Called once module is loaded
- */
-int USB_Install(char **Arguments)
-{
-       UHCI_Initialise();
-       Warning("[USB  ] Not Complete - Devel Only");
-       return 1;
-}
-
-/**
- * \fn void USB_Cleanup()
- * \brief Called just before module is unloaded
- */
-void USB_Cleanup()
-{
-}
-
-/**
- * \fn char *USB_ReadDir(tVFS_Node *Node, int Pos)
- * \brief Read from the USB root
- */
-char *USB_ReadDir(tVFS_Node *Node, int Pos)
-{
-       return NULL;
-}
-
-/**
- * \fn tVFS_Node *USB_FindDir(tVFS_Node *Node, char *Name)
- * \brief Locate an entry in the USB root
- */
-tVFS_Node *USB_FindDir(tVFS_Node *Node, char *Name)
-{
-       return NULL;
-}
-
-/**
- * \brief Handles IOCtl Calls to the USB driver
- */
-int USB_IOCtl(tVFS_Node *Node, int Id, void *Data)
-{
-       return 0;
-}
diff --git a/Modules/USB/uhci.c b/Modules/USB/uhci.c
deleted file mode 100644 (file)
index e8cb7b7..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/*\r
- * Acess 2 USB Stack\r
- * Universal Host Controller Interface\r
- */\r
-#define DEBUG  1\r
-#include <acess.h>\r
-#include <vfs.h>\r
-#include <drv_pci.h>\r
-#include "usb.h"\r
-#include "uhci.h"\r
-\r
-// === CONSTANTS ===\r
-#define        MAX_CONTROLLERS 4\r
-#define NUM_TDs        1024\r
-\r
-// === PROTOTYPES ===\r
- int   UHCI_Initialise();\r
-void   UHCI_Cleanup();\r
- int   UHCI_IOCtl(tVFS_Node *node, int id, void *data);\r
- int   UHCI_Int_InitHost(tUHCI_Controller *Host);\r
-\r
-// === GLOBALS ===
-//Uint gaFrameList[1024];\r
-tUHCI_TD       gaUHCI_TDPool[NUM_TDs];\r
-tUHCI_Controller       gUHCI_Controllers[MAX_CONTROLLERS];\r
-\r
-// === CODE ===\r
-/**\r
- * \fn int UHCI_Initialise()\r
- * \brief Called to initialise the UHCI Driver\r
- */\r
-int UHCI_Initialise()\r
-{\r
-        int    i=0, id=-1;\r
-        int    ret;\r
-       Uint16  base;\r
-       \r
-       ENTER("");\r
-       \r
-       // Enumerate PCI Bus, getting a maximum of `MAX_CONTROLLERS` devices\r
-       while( (id = PCI_GetDeviceByClass(0x0C03, 0xFFFF, id)) >= 0 && i < MAX_CONTROLLERS )\r
-       {\r
-               gUHCI_Controllers[i].PciId = id;\r
-               // Assign a port range (BAR4, Reserve 32 ports)\r
-               base = PCI_AssignPort( id, 4, 0x20 );\r
-               gUHCI_Controllers[i].IOBase = base;\r
-               \r
-               Log("[USB  ] Controller PCI #%i: IO Base = 0x%x", id, base);\r
-               \r
-               // Initialise Host\r
-               ret = UHCI_Int_InitHost(&gUHCI_Controllers[i]);\r
-               // Detect an error\r
-               if(ret != 0) {\r
-                       LEAVE('i', ret);\r
-                       return ret;\r
-               }\r
-               \r
-               i ++;\r
-       }\r
-       if(i == MAX_CONTROLLERS) {\r
-               Warning("[UHCI ] Over "EXPAND_STR(MAX_CONTROLLERS)" UHCI controllers detected, ignoring rest");\r
-       }\r
-       LEAVE('i', i);\r
-       return i;\r
-}\r
-\r
-/**\r
- * \fn void UHCI_Cleanup()\r
- * \brief Called just before module is unloaded\r
- */\r
-void UHCI_Cleanup()\r
-{\r
-}
-\r
-/**\r
- * \brief Sends a packet to a device endpoint\r
- */\r
-int UHCI_SendPacket(int ControllerId, int Length)\r
-{\r
-       //tUHCI_TD      *td = UHCI_AllocateTD();\r
-       return 0;\r
-}\r
-\r
-// === INTERNAL FUNCTIONS ===\r
-/**\r
- * \fn int UHCI_Int_InitHost(tUCHI_Controller *Host)\r
- * \brief Initialises a UHCI host controller\r
- * \param Host Pointer - Host to initialise\r
- */\r
-int UHCI_Int_InitHost(tUHCI_Controller *Host)\r
-{\r
-       ENTER("pHost", Host);\r
-       \r
-       // Allocate Frame List\r
-       Host->FrameList = (void *) MM_AllocDMA(1, 32, &Host->PhysFrameList);    // 1 Page, 32-bit\r
-       if( !Host->FrameList ) {\r
-               Warning("[UHCI ] Unable to allocate frame list, aborting");\r
-               LEAVE('i', -1);\r
-               return -1;\r
-       }\r
-       LOG("Allocated frame list 0x%x (0x%x)", Host->FrameList, Host->PhysFrameList);\r
-       memsetd( Host->FrameList, 1, 1024 );    // Clear List (Disabling all entries)\r
-       \r
-       //! \todo Properly fill frame list\r
-       \r
-       // Set frame length to 1 ms\r
-       outb( Host->IOBase + SOFMOD, 64 );\r
-       \r
-       // Set Frame List Address\r
-       outd( Host->IOBase + FLBASEADD, Host->PhysFrameList );\r
-       \r
-       // Set Frame Number\r
-       outw( Host->IOBase + FRNUM, 0 );\r
-       \r
-       // Enable Interrupts\r
-       //PCI_WriteWord( Host->PciId, 0xC0, 0x2000 );\r
-       \r
-       LEAVE('i', 0);\r
-       return 0;\r
-}\r
diff --git a/Modules/USB/uhci.h b/Modules/USB/uhci.h
deleted file mode 100644 (file)
index df7854b..0000000
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * AcessOS Version 1
- * USB Stack
- * - Universal Host Controller Interface
- */
-#ifndef _UHCI_H_
-#define _UHCI_H_
-
-// === TYPES ===
-typedef struct sUHCI_Controller        tUHCI_Controller;
-typedef struct sUHCI_TD        tUHCI_TD;
-typedef struct sUHCI_QH        tUHCI_QH;
-
-// === STRUCTURES ===
-struct sUHCI_Controller
-{
-       /**
-        * \brief PCI Device ID
-        */
-       Uint16  PciId;
-       
-       /**
-        * \brief IO Base Address
-        */
-       Uint16  IOBase;
-       
-       /**
-        * \brief Frame list
-        * 
-        * 31:4 - Frame Pointer
-        * 3:2 - Reserved
-        * 1 - QH/TD Selector
-        * 0 - Terminate (Empty Pointer)
-        */
-       Uint32  *FrameList;
-       
-       /**
-        * \brief Physical Address of the Frame List
-        */
-       tPAddr  PhysFrameList;
-};
-
-struct sUHCI_TD
-{
-       /**
-        * \brief Next Entry in list
-        * 
-        * 31:4 - Address
-        * 3 - Reserved
-        * 2 - Depth/Breadth Select
-        * 1 - QH/TD Select
-        * 0 - Terminate (Last in List)
-        */
-       Uint32  Link;
-       
-       /**
-        * \brief Control and Status Field
-        * 
-        * 31:30 - Reserved
-        * 29 - Short Packet Detect (Input Only)
-        * 28:27 - Number of Errors Allowed
-        * 26 - Low Speed Device (Communicating with a low speed device)
-        * 25 - Isynchonious Select
-        * 24 - Interrupt on Completion (IOC)
-        * 23:16 - Status
-        *     23 - Active
-        *     22 - Stalled
-        *     21 - Data Buffer Error
-        *     20 - Babble Detected
-        *     19 - NAK Detected
-        *     18 - CRC/Timout Error
-        *     17 - Bitstuff Error
-        *     16 - Reserved
-        * 15:11 - Reserved
-        * 10:0 - Actual Length (Number of bytes transfered)
-        */
-       Uint32  Control;
-       
-       /**
-        * \brief Packet Header
-        * 
-        * 31:21 - Maximum Length (0=1, Max 0x4FF, 0x7FF=0)
-        * 20 - Reserved
-        * 19 - Data Toggle
-        * 18:15 - Endpoint
-        * 14:8 - Device Address
-        * 7:0 - PID (Packet Identifcation) - Only 96, E1, 2D allowed
-        */
-       Uint32  Token;
-       
-       /**
-        * \brief Pointer to the data to send
-        */
-       Uint32  BufferPointer;
-};
-
-struct sUHCI_QH
-{
-       /**
-        * \brief Next Entry in list
-        * 
-        * 31:4 - Address
-        * 3:2 - Reserved
-        * 1 - QH/TD Select
-        * 0 - Terminate (Last in List)
-        */
-       Uint32  Next;
-
-       
-       /**
-        * \brief Next Entry in list
-        * 
-        * 31:4 - Address
-        * 3:2 - Reserved
-        * 1 - QH/TD Select
-        * 0 - Terminate (Last in List)
-        */
-       Uint32  Child;
-};
-
-// === ENUMERATIONS ===
-enum eUHCI_IOPorts {
-       /**
-        * \brief USB Command Register
-        * 
-        * 15:8 - Reserved
-        * 7 - Maximum Packet Size selector (1: 64 bytes, 0: 32 bytes)
-        * 6 - Configure Flag (No Hardware Effect)
-        * 5 - Software Debug (Don't think it will be needed)
-        * 4 - Force Global Resume
-        * 3 - Enter Global Suspend Mode
-        * 2 - Global Reset (Resets all devices on the bus)
-        * 1 - Host Controller Reset (Reset just the controller)
-        * 0 - Run/Stop
-        */
-       USBCMD  = 0x00,
-       /**
-        * \brief USB Status Register
-        * 
-        * 15:6 - Reserved
-        * 5 - HC Halted, set to 1 when USBCMD:RS is set to 0
-        * 4 - Host Controller Process Error (Errors related to the bus)
-        * 3 - Host System Error (Errors related to the OS/PCI Bus)
-        * 2 - Resume Detect (Set if a RESUME command is sent to the Controller)
-        * 1 - USB Error Interrupt
-        * 0 - USB Interrupts (Set if a transaction with the IOC bit set is completed)
-        */
-       USBSTS  = 0x02,
-       /**
-        * \brief USB Interrupt Enable Register
-        * 
-        * 15:4 - Reserved
-        * 3 - Short Packet Interrupt Enable
-        * 2 - Interrupt on Complete (IOC) Enable
-        * 1 - Resume Interrupt Enable
-        * 0 - Timout / CRC Error Interrupt Enable
-        */
-       USBINTR = 0x04,
-       /**
-        * \brief Frame Number (Index into the Frame List)
-        * 
-        * 15:11 - Reserved
-        * 10:0 - Index (Incremented each approx 1ms)
-        */
-       FRNUM   = 0x06,
-       /**
-        * \brief Frame List Base Address
-        * 
-        * 31:12 - Pysical Address >> 12
-        * 11:0 - Reserved (Set to Zero)
-        */
-       FLBASEADD = 0x08,       // 32-bit
-       /**
-        * \brief Start-of-frame Modify Register
-        * \note 8-bits only
-        * 
-        * Sets the size of a frame
-        * Frequency = (11936+n)/12000 kHz
-        * 
-        * 7 - Reserved
-        * 6:0 -
-        */
-       SOFMOD = 0x0C,  // 8bit
-       /**
-        * \brief Port Status and Controll Register (Port 1)
-        * 
-        * 15:13 - Reserved
-        * 12 - Suspend
-        * 11:10 - Reserved
-        * 9 - Port Reset
-        * 8 - Low Speed Device Attached
-        * 5:4 - Line Status
-        * 3 - Port Enable/Disable Change - Used for detecting device removal
-        * 2 - Port Enable/Disable
-        * 1 - Connect Status Change
-        * 0 - Current Connect Status
-        */
-       PORTSC1 = 0x10,
-       /**
-        * \brief Port Status and Controll Register (Port 2)
-        * 
-        * See ::PORTSC1
-        */
-       PORTSC2 = 0x12
-};
-
-#endif
diff --git a/Modules/USB/usb.c b/Modules/USB/usb.c
deleted file mode 100644 (file)
index 4663ce2..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Acess 2 USB Stack
- * USB Packet Control
- */
-#define DEBUG  1
-#include <acess.h>
-#include <vfs.h>
-#include <drv_pci.h>
-#include "usb.h"
-
-
-// === CODE ===
-void USB_MakeToken(void *Buf, int PID, int Addr, int EndP)
-{
-       Uint8   *tok = Buf;
-        int    crc = 0;        //USB_TokenCRC();
-       
-       tok[0] = PID;
-       tok[1] = Addr | ((EndP&1)<<7);
-       tok[2] = (EndP >> 1) | crc;
-}
-
-#if 0
-void USB_SendPacket(int Controller, int PID, int Dev, int Endpoint, void *Data, int Length)
-{
-       uint8_t buf[Length/*+??*/];
-       switch(Controller & 0xF00)
-       {
-       case 1:
-               UHCI_SendPacket(Controller & 0xFF);
-       }
-}
-#endif
diff --git a/Modules/USB/usb.h b/Modules/USB/usb.h
deleted file mode 100644 (file)
index a867c11..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * AcessOS Version 1
- * USB Stack
- */
-#ifndef _USB_H_
-#define _USB_H_
-
-// === TYPES ===
-typedef struct sUSBHost        tUSBHost;
-typedef struct sUSBDevice      tUSBDevice;
-
-// === CONSTANTS ===
-enum eUSB_PIDs
-{
-       /**
-        * \name Token
-        * \{
-        */
-       PID_OUT         = 0xE1,
-       PID_IN          = 0x69,
-       PID_SOF         = 0xA5,
-       PID_SETUP       = 0x2D,
-       /**
-        * \}
-        */
-       
-       /**
-        * \name Data
-        * \{
-        */
-       PID_DATA0       = 0xC3,
-       PID_DATA1       = 0x4B,
-       PID_DATA2       = 0x87, // USB2 only
-       PID_MDATA       = 0x0F, // USB2 only
-       /**
-        * \}
-        */
-       
-       /**
-        * \name Handshake
-        * \{
-        */
-       PID_ACK         = 0xD2,
-       PID_NAK         = 0x5A,
-       PID_STALL       = 0x1E,
-       PID_NYET        = 0x96,
-       /**
-        * \}
-        */
-       
-       /**
-        * \name Special
-        * \{
-        */
-       PID_PRE         = 0x3C, PID_ERR         = 0x3C,
-       PID_SPLIT       = 0x78,
-       PID_PING        = 0xB4,
-       PID_RESVD       = 0xF0,
-       /**
-        * \}
-        */
-};
-
-// === FUNCTIONS ===
-/**
- * \note 00101 - X^5+X^2+1
- */
-Uint8  USB_TokenCRC(void *Data, int len);
-/**
- * \note X^16 + X15 + X^2 + 1
- */
-Uint16 USB_DataCRC(void *Data, int len);
-
-// === STRUCTURES ===
-/**
- * \brief Defines a USB Host Controller
- */
-struct sUSBHost
-{
-       Uint16  IOBase;
-       
-        int    (*SendPacket)(int ID, int Length, void *Data);
-};
-
-/**
- * \brief Defines a single device on the USB Bus
- */
-struct sUSBDevice
-{
-       tUSBHost        *Host;
-};
-
-#endif
index 01b49ee..ef77048 100644 (file)
@@ -3,6 +3,7 @@
 -include ../Makefile.cfg\r
 \r
 CPPFLAGS += -I./include\r
+LDFLAGS += -lreadline\r
 \r
 BIN = ../CLIShell\r
 OBJ = main.o lib.o\r
index 1f381e2..579df88 100644 (file)
@@ -1,12 +1,17 @@
 /*\r
  * AcessOS Shell Version 3\r
  */\r
+#define USE_READLINE   0\r
 #include <acess/sys.h>\r
 #include <stdlib.h>\r
 #include <stdio.h>\r
 #include <string.h>\r
 #include "header.h"\r
 \r
+#if USE_READLINE\r
+# include "readline.h"\r
+#endif\r
+\r
 #define _stdin 0\r
 #define _stdout        1\r
 #define _stderr        2\r
@@ -51,7 +56,15 @@ int main(int argc, char *argv[], char *envp[])
         int    length = 0;\r
         int    i;\r
         int    iArgCount = 0;\r
+       #if !USE_READLINE\r
         int    bCached = 1;\r
+       #else\r
+       tReadline       readline_state = {0};\r
+       #endif\r
+       \r
+       #if USE_READLINE\r
+       readline_state.UseHistory = 1;\r
+       #endif\r
        \r
        gasEnvironment = envp;\r
        \r
@@ -74,13 +87,19 @@ int main(int argc, char *argv[], char *envp[])
        {\r
                // Free last command & arguments\r
                if(saArgs[0])   free(saArgs);\r
+               #if !USE_READLINE\r
                if(!bCached)    free(sCommandStr);\r
                bCached = 0;\r
+               #endif\r
                \r
                write(_stdout, strlen(gsCurrentDirectory), gsCurrentDirectory);\r
                write(_stdout, 2, "$ ");\r
                \r
                // Read Command line\r
+               #if USE_READLINE\r
+               sCommandStr = Readline( &readline_state );\r
+               length = strlen(sCommandStr);\r
+               #else\r
                sCommandStr = ReadCommandLine( &length );\r
                \r
                if(!sCommandStr) {\r
@@ -99,6 +118,7 @@ int main(int argc, char *argv[], char *envp[])
                        gasCommandHistory[ giLastCommand ] = sCommandStr;\r
                        bCached = 1;\r
                }\r
+               #endif\r
                \r
                // Parse Command Line into arguments\r
                Parse_Args(sCommandStr, saArgs);\r
@@ -123,6 +143,10 @@ int main(int argc, char *argv[], char *envp[])
                \r
                // Shall we?\r
                CallCommand( &saArgs[1] );\r
+               \r
+               #if USE_READLINE\r
+               free( sCommandStr );\r
+               #endif\r
        }\r
 }\r
 \r
diff --git a/Usermode/Applications/axwin2_src/Shell_src/Makefile b/Usermode/Applications/axwin2_src/Shell_src/Makefile
new file mode 100644 (file)
index 0000000..18c4ab1
--- /dev/null
@@ -0,0 +1,12 @@
+# Project: Acess GUI Default Shell
+
+-include ../../Makefile.cfg
+
+CPPFLAGS += -I../include
+LDFLAGS += -laxwin2
+
+DIR = Apps/AxWin/1.0
+BIN = ../Shell
+OBJ = main.o
+
+-include ../../Makefile.tpl
diff --git a/Usermode/Applications/axwin2_src/Shell_src/main.c b/Usermode/Applications/axwin2_src/Shell_src/main.c
new file mode 100644 (file)
index 0000000..b357dea
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Acess2 GUI Shell
+ * - By John Hodge (thePowersGang)
+ */
+#include <axwin/axwin.h>
+
+// === PROTOTYPES ===
+ int   main(int argc, char *argv[]);
+ int   Menubar_HandleMessage(tAxWin_Message *Message);
+
+// === GLOBALS ===
+tAxWin_Handle  ghMenubarWindow;
+
+// === CODE ===
+int main(int argc, char *argv[])
+{      
+       // Create Window
+       ghMenubarWindow = AxWin_CreateWindow(0, 0, -1, -1, WINFLAG_NOBORDER, Menubar_HandleMessage);
+       
+       AxWin_MessageLoop();
+       
+       return 0;
+}
+
+/**
+ */
+int Menubar_HandleMessage(tAxWin_Message *Message)
+{
+       return 0;
+}
index 0b3e8fc..13379fa 100644 (file)
@@ -9,6 +9,9 @@
 #include <stdio.h>
 #include <stdint.h>
 
+#include "wm.h"
+
+// === GLOBALS ===
 extern char    *gsTerminalDevice;
 extern char    *gsMouseDevice;
 
diff --git a/Usermode/Applications/axwin2_src/WM/wm.h b/Usermode/Applications/axwin2_src/WM/wm.h
new file mode 100644 (file)
index 0000000..e7b6bee
--- /dev/null
@@ -0,0 +1,34 @@
+
+#ifndef _WM_H_
+#define _WM_H_
+
+typedef struct sElement
+{
+       struct sElement *NextSibling;
+       
+       short   CachedX;
+       short   CachedY;
+       short   CachedW;
+       short   CachedH;
+       
+       struct sElement *FirstChild;
+}      tElement;
+
+typedef struct sTab
+{
+       char    *Name;
+       
+       tElement        *RootElement;
+}      tTab;
+
+typedef struct sApplication
+{
+       pid_t   PID;
+       
+        int    nTabs;
+       tTab    *Tabs;
+       
+       char    Name[];
+}      tApplication;
+
+#endif
index 1cff6d9..ba78838 100644 (file)
@@ -70,6 +70,13 @@ void DumpInterfaces(int DumpAll)
                type = ioctl(fd, 4, NULL);
                
                printf("%s:\t", filename);
+               {
+                       int len = ioctl(fd, ioctl(fd, 3, "get_device"), NULL);
+                       char *buf = malloc(len+1);
+                       ioctl(fd, ioctl(fd, 3, "get_device"), buf);
+                       printf("'%s'\t", buf);
+                       free(buf);
+               }
                switch(type)
                {
                case 0:
index b84e85f..1608108 100644 (file)
@@ -6,11 +6,11 @@
 #include <stdio.h>
 
 #define        MOUNTABLE_FILE  "/Acess/Conf/Mountable"
-#define        MOUNTED_FILE    "/Acess/Conf/Mounted"
+#define        MOUNTED_FILE    "/Devices/System/VFS/Mounts"
 
 // === PROTOTYPES ===
 void   ShowUsage();
- int   GetMountDefs(char **spDevice, char **spDir, char **spType, char **spOptions);
+ int   GetMountDefs(char *Ident, char **spDevice, char **spDir, char **spType, char **spOptions);
 
 // === CODE ===
 /**
@@ -41,6 +41,7 @@ int main(int argc, char *argv[])
                {
                        switch(arg[1])
                        {
+                       // -t <driver> :: Filesystem driver to use
                        case 't':       sType = argv[++i];      break;
                        case '-':
                                //TODO: Long Arguments
@@ -51,11 +52,13 @@ int main(int argc, char *argv[])
                        continue;
                }
                
+               // Device?
                if(sDevice == NULL) {
                        sDevice = arg;
                        continue;
                }
                
+               // Directory?
                if(sDir == NULL) {
                        sDir = arg;
                        continue;
@@ -77,7 +80,8 @@ int main(int argc, char *argv[])
        if(sDir == NULL || getuid() != 0)
        {
                // Check if it is defined in the mounts file
-               if(GetMountDefs(&sDevice, &sDir, &sType, &sOptions) == 0)
+               // - At this point sDevice could be a device name or a mount point
+               if(GetMountDefs(sDevice, &sDevice, &sDir, &sType, &sOptions) == 0)
                {
                        if(sDir == NULL)
                                fprintf(stderr, "Unable to find '%s' in '%s'\n",
@@ -136,12 +140,12 @@ void ShowUsage(char *ProgName)
 }
 
 /**
- * \fn int GetMountDefs(char **spDevice, char **spDir, char **spType, char **spOptions)
+ * \fn int GetMountDefs(char *Ident, char **spDevice, char **spDir, char **spType, char **spOptions)
  * \brief Reads the mountable definitions file and returns the corresponding entry
  * \param spDevice     Pointer to a string (pointer) determining the device (also is the input for this function)
  * \note STUB
  */
-int GetMountDefs(char **spDevice, char **spDir, char **spType, char **spOptions)
+int GetMountDefs(char *Ident, char **spDevice, char **spDir, char **spType, char **spOptions)
 {
        // TODO: Read the mounts file (after deciding what it will be)
        return 0;
index fcd6ad6..788da48 100644 (file)
@@ -1,4 +1,4 @@
-module /Acess/Modules/bochsvbe.kmd
+#module /Acess/Modules/bochsvbe.kmd
 #module /Acess/Modules/ps2mouse
 #edimod /Acess/Modules/serial.edi
 #module /Acess/Modules/ne2000.akm
diff --git a/Usermode/Libraries/Makefile.tpl b/Usermode/Libraries/Makefile.tpl
new file mode 100644 (file)
index 0000000..709aaac
--- /dev/null
@@ -0,0 +1,18 @@
+# Acess 2 SQLite 3 Library
+#
+
+.PHONY: all clean install
+
+all: $(BIN)
+
+clean:
+       $(RM) $(BIN) $(OBJ)
+
+install: $(BIN)
+       $(xCP) $(BIN) $(DISTROOT)/Libs/
+
+$(BIN): $(OBJ)
+       $(LD) $(LDFLAGS) -o $(BIN) $(OBJ)
+
+%.o: %.c
+       $(CC) $(CFLAGS) -o $@ -c $<
index 324836b..f191556 100644 (file)
@@ -2,8 +2,7 @@
 #
 #
 
-AS = nasm
-RM = rm -f
+-include ../Makefile.cfg
 
 ASFLAGS = -felf
 
index b5fb0a1..5cfa26e 100644 (file)
@@ -66,6 +66,10 @@ Uint LoadLibrary(char *SoName, char *SearchDir, char **envp)
        \r
        // Create Temp Name\r
        filename = FindLibrary(sTmpName, SoName, SearchDir);\r
+       if(filename == NULL) {\r
+               DEBUGS("LoadLibrary: RETURN 0\n");\r
+               return 0;\r
+       }\r
        DEBUGS(" LoadLibrary: filename='%s'\n", filename);\r
        \r
        if( (iArg = IsFileLoaded(filename)) )\r
diff --git a/Usermode/Libraries/libaxwin2.so_src/Makefile b/Usermode/Libraries/libaxwin2.so_src/Makefile
new file mode 100644 (file)
index 0000000..5529140
--- /dev/null
@@ -0,0 +1,13 @@
+# Acess 2 - AxWin GUI Library
+#
+
+include ../Makefile.cfg
+
+CPPFLAGS +=
+CFLAGS   += -Wall
+LDFLAGS  += -lc -soname libaxwin2.so
+
+OBJ = main.o messages.o windows.o
+BIN = ../libaxwin2.so
+
+include ../Makefile.tpl
diff --git a/Usermode/Libraries/libaxwin2.so_src/common.h b/Usermode/Libraries/libaxwin2.so_src/common.h
new file mode 100644 (file)
index 0000000..28d2839
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * AxWin Window Manager Interface Library
+ * By John Hodge (thePowersGang)
+ * This file is published under the terms of the Acess Licence. See the
+ * file COPYING for details.
+ * 
+ * common.h - Internal Variable and Constant definitions
+ */
+#ifndef _COMMON_H_
+#define _COMMON_H_
+
+// === Includes ===
+#include <acess/sys.h>
+#include <axwin/axwin.h>
+#include <stdlib.h>
+
+// === Constants ===
+enum eAxWin_Modes
+{
+       AXWIN_MODE_IPC
+};
+
+// === Variables ===
+extern int     giAxWin_Mode;
+
+#endif
diff --git a/Usermode/Libraries/libaxwin2.so_src/main.c b/Usermode/Libraries/libaxwin2.so_src/main.c
new file mode 100644 (file)
index 0000000..1a12561
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * AxWin Window Manager Interface Library
+ * By John Hodge (thePowersGang)
+ * This file is published under the terms of the Acess Licence. See the
+ * file COPYING for details.
+ * 
+ * main.c - Library Initialisation
+ */
+#include "common.h"
+
+// === GLOBALS ===
+ int   giAxWin_Mode = 0;
+
+// === CODE ===
+int SoMain()
+{
+       return 0;
+}
diff --git a/Usermode/Libraries/libaxwin2.so_src/messages.c b/Usermode/Libraries/libaxwin2.so_src/messages.c
new file mode 100644 (file)
index 0000000..d0fc5da
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * AxWin Window Manager Interface Library
+ * By John Hodge (thePowersGang)
+ * This file is published under the terms of the Acess Licence. See the
+ * file COPYING for details.
+ * 
+ * messages.c - Message Handling
+ */
+#include "common.h"
+
+// === PROTOTYPES ===
+ int   AxWin_MessageLoop();
+tAxWin_Message *AxWin_WaitForMessage();
+ int   AxWin_HandleMessage(tAxWin_Message *Message);
+
+// === CODE ===
+/**
+ * \brief Loop forever, checking and waiting for messages
+ */
+int AxWin_MessageLoop()
+{
+       tAxWin_Message  *msg;
+        int    ret;
+       for(;;)
+       {
+               msg = AxWin_WaitForMessage();
+               ret = AxWin_HandleMessage(msg);
+               
+               if(ret < 0)     return 0;
+       }
+       return 0;
+}
+
+/**
+ * \brief Wait for a message
+ */
+tAxWin_Message *AxWin_WaitForMessage()
+{
+        int    length;
+       pid_t   src;
+       tAxWin_Message  *ret;
+       
+       switch( giAxWin_Mode )
+       {
+       case AXWIN_MODE_IPC:
+               while( (length = SysGetMessage(&src, NULL)) == 0 )      sleep();
+               ret = malloc(length);
+               SysGetMessage(NULL, ret);
+               break;
+       default:
+               break;
+       }
+       return 0;
+}
+
+/**
+ * \brief Handles a recieved message
+ */
+int AxWin_HandleMessage(tAxWin_Message *Message)
+{
+       switch(Message->ID)
+       {
+       default:        return 0;
+       }
+}
diff --git a/Usermode/Libraries/libaxwin2.so_src/windows.c b/Usermode/Libraries/libaxwin2.so_src/windows.c
new file mode 100644 (file)
index 0000000..a37bfbb
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * AxWin Window Manager Interface Library
+ * By John Hodge (thePowersGang)
+ * This file is published under the terms of the Acess Licence. See the
+ * file COPYING for details.
+ * 
+ * window.c - Window Control
+ */
+#include "common.h"
+
+// === TYPES & STRUCTURES ===
+struct sAxWin_Window
+{
+       struct sAxWin_Window    *Next;
+       uint32_t        WmHandle;
+       tAxWin_MessageCallback  Callback;
+};
+
+// === PROTOTYPES ===
+tAxWin_Handle  AxWin_CreateWindow(
+       int16_t X, int16_t Y, int16_t W, int16_t H,
+       uint32_t Flags, tAxWin_MessageCallback *Callback
+       );
+
+// === GLOBALS ===
+//mutex_t      glProcessWindows;
+tAxWin_Window  *gProcessWindows;
+
+// === CODE ===
+tAxWin_Handle  AxWin_CreateWindow(
+       int16_t X, int16_t Y,
+       int16_t W, int16_t H,
+       uint32_t Flags, tAxWin_MessageCallback *Callback)
+{
+       tAxWin_Message  req;
+       tAxWin_Message  *msg;
+       tAxWin_Window   *win;
+       
+       req.ID = MSG_SREQ_NEWWINDOW;
+       req.Size = 1 + sizeof(struct sAxWin_SReq_NewWindow)/4;
+       req.SReq_NewWindow.X = X;
+       req.SReq_NewWindow.Y = Y;
+       req.SReq_NewWindow.W = W;
+       req.SReq_NewWindow.H = H;
+       req.SReq_NewWindow.Flags = Flags;
+       
+       AxWin_SendMessage(&msg);
+       
+       for(;;)
+       {
+               msg = AxWin_WaitForMessage();
+               
+               if(msg.ID == MSG_SRSP_WINDOW)
+                       break;
+               
+               AxWin_HandleMessage(msg);
+               free(msg);
+       }
+       
+       win = malloc(sizeof(tAxWin_Window));
+       win->WmHandle = msg->SRsp_Window.Handle;
+       win->Callback = Callback;
+       
+       //mutex_acquire(glProcessWindows);
+       win->Next = gProcessWindows;
+       gProcessWindows = win;
+       //mutex_release(glProcessWindows);
+       
+       return 0;
+}
diff --git a/Usermode/Libraries/libreadline.so_src/Makefile b/Usermode/Libraries/libreadline.so_src/Makefile
new file mode 100644 (file)
index 0000000..fefbf0c
--- /dev/null
@@ -0,0 +1,13 @@
+# Acess 2 - AxWin GUI Library
+#
+
+include ../Makefile.cfg
+
+CPPFLAGS +=
+CFLAGS   += -Wall
+LDFLAGS  += -lc -soname libreadline.so
+
+OBJ = main.o
+BIN = ../libreadline.so
+
+include ../Makefile.tpl
index f2ddf68..3af20ee 100644 (file)
@@ -5,14 +5,31 @@
  * Text mode entry with history
  */
 #include <readline.h>
+#include <acess/sys.h>
 #include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#define STDIN_FD       0
+#define STDOUT_FD      1
+
+// === PROTOTYPES ===
+ int   SoMain();
+tReadline      *Readline_CreateInstance(int bUseHistory);
+char   *Readline(tReadline *Info);
 
 // === GLOBALS ===
 
 // === CODE ===
+int SoMain()
+{
+       return 0;
+}
+
 char *Readline(tReadline *Info)
 {
        char    *ret;
+       char    *orig;
         int    len, pos, space = 1023-8-8;     // optimised for the heap manager
        char    ch;
         int    scrollbackPos = Info->NumHistory;
@@ -21,10 +38,12 @@ char *Readline(tReadline *Info)
        ret = malloc( space+1 );
        if(!ret)        return NULL;
        len = 0;        pos = 0;
-               
+       
+       orig = ret;
+       
        // Read In Command Line
        do {
-               read(_stdin, 1, &ch);   // Read Character from stdin (read is a blocking call)
+               read(STDIN_FD, 1, &ch); // Read Character from stdin (read is a blocking call)
                
                if(ch == '\n')  break;
                
@@ -32,13 +51,13 @@ char *Readline(tReadline *Info)
                {
                // Control characters
                case '\x1B':
-                       read(_stdin, 1, &ch);   // Read control character
+                       read(STDIN_FD, 1, &ch); // Read control character
                        switch(ch)
                        {
                        //case 'D':     if(pos) pos--;  break;
                        //case 'C':     if(pos<len)     pos++;  break;
                        case '[':
-                               read(_stdin, 1, &ch);   // Read control character
+                               read(STDIN_FD, 1, &ch); // Read control character
                                switch(ch)
                                {
                                case 'A':       // Up
@@ -46,13 +65,13 @@ char *Readline(tReadline *Info)
                                                 int    oldLen = len;
                                                if( scrollbackPos <= 0 )        break;
                                                
-                                               free(ret);
+                                               if(ret != orig) free(ret);
                                                ret = strdup( Info->History[--scrollbackPos] );
                                                
-                                               len = strlen(ret);
-                                               while(pos--)    write(_stdout, 3, "\x1B[D");
-                                               write(_stdout, len, ret);       pos = len;
-                                               while(pos++ < oldLen)   write(_stdout, 1, " ");
+                                               space = len = strlen(ret);
+                                               while(pos-->1)  write(STDOUT_FD, 3, "\x1B[D");
+                                               write(STDOUT_FD, len, ret);     pos = len;
+                                               while(pos++ < oldLen)   write(STDOUT_FD, 1, " ");
                                        }
                                        break;
                                case 'B':       // Down
@@ -60,24 +79,24 @@ char *Readline(tReadline *Info)
                                                 int    oldLen = len;
                                                if( scrollbackPos >= Info->NumHistory ) break;
                                                
-                                               free(ret);
+                                               if(ret != orig) free(ret);
                                                ret = strdup( Info->History[scrollbackPos++] );
                                                
-                                               len = strlen(ret);
-                                               while(pos--)    write(_stdout, 3, "\x1B[D");
-                                               write(_stdout, len, ret);       pos = len;
-                                               while(pos++ < oldLen)   write(_stdout, 1, " ");
+                                               space = len = strlen(ret);
+                                               while(pos-->1)  write(STDOUT_FD, 3, "\x1B[D");
+                                               write(STDOUT_FD, len, ret);     pos = len;
+                                               while(pos++ < oldLen)   write(STDOUT_FD, 1, " ");
                                        }
                                        break;
                                case 'D':       // Left
                                        if(pos == 0)    break;
                                        pos --;
-                                       write(_stdout, 3, "\x1B[D");
+                                       write(STDOUT_FD, 3, "\x1B[D");
                                        break;
                                case 'C':       // Right
                                        if(pos == len)  break;
                                        pos++;
-                                       write(_stdout, 3, "\x1B[C");
+                                       write(STDOUT_FD, 3, "\x1B[C");
                                        break;
                                }
                        }
@@ -86,7 +105,7 @@ char *Readline(tReadline *Info)
                // Backspace
                case '\b':
                        if(len <= 0)            break;  // Protect against underflows
-                       write(_stdout, 1, &ch);
+                       write(STDOUT_FD, 1, &ch);
                        if(pos == len) {        // Simple case of end of string
                                len --;
                                pos--;
@@ -96,9 +115,9 @@ char *Readline(tReadline *Info)
                                buf[2] += ((len-pos+1)/100) % 10;
                                buf[3] += ((len-pos+1)/10) % 10;
                                buf[4] += (len-pos+1) % 10;
-                               write(_stdout, len-pos, &ret[pos]);     // Move Text
-                               ch = ' ';       write(_stdout, 1, &ch); ch = '\b';      // Clear deleted character
-                               write(_stdout, 7, buf); // Update Cursor
+                               write(STDOUT_FD, len-pos, &ret[pos]);   // Move Text
+                               ch = ' ';       write(STDOUT_FD, 1, &ch);       ch = '\b';      // Clear deleted character
+                               write(STDOUT_FD, 7, buf);       // Update Cursor
                                // Alter Buffer
                                memmove(&ret[pos-1], &ret[pos], len-pos);
                                pos --;
@@ -116,7 +135,12 @@ char *Readline(tReadline *Info)
                        // Expand Buffer
                        if(len+1 > space) {
                                space += 256;
-                               ret = realloc(ret, space+1);
+                               if(ret == orig) {
+                                       orig = ret = realloc(ret, space+1);
+                               }
+                               else {
+                                       ret = realloc(ret, space+1);
+                               }
                                if(!ret)        return NULL;
                        }
                        
@@ -126,13 +150,13 @@ char *Readline(tReadline *Info)
                                buf[2] += ((len-pos)/100) % 10;
                                buf[3] += ((len-pos)/10) % 10;
                                buf[4] += (len-pos) % 10;
-                               write(_stdout, 1, &ch); // Print new character
-                               write(_stdout, len-pos, &ret[pos]);     // Move Text
-                               write(_stdout, 7, buf); // Update Cursor
+                               write(STDOUT_FD, 1, &ch);       // Print new character
+                               write(STDOUT_FD, len-pos, &ret[pos]);   // Move Text
+                               write(STDOUT_FD, 7, buf);       // Update Cursor
                                memmove( &ret[pos+1], &ret[pos], len-pos );
                        }
                        else {
-                               write(_stdout, 1, &ch);
+                               write(STDOUT_FD, 1, &ch);
                        }
                        ret[pos++] = ch;
                        len ++;
@@ -150,7 +174,7 @@ char *Readline(tReadline *Info)
        // Add to history
        if( Info->UseHistory )
        {
-               if( strcmp( Info->History[ Info->NumHistory-1 ], ret) != 0 )
+               if( !Info->History || strcmp( Info->History[ Info->NumHistory-1 ], ret) != 0 )
                {
                        void    *tmp;
                        Info->NumHistory ++;
@@ -163,5 +187,7 @@ char *Readline(tReadline *Info)
                }
        }
        
+       if(ret != orig) free(orig);
+       
        return ret;
 }
diff --git a/Usermode/include/axwin/axwin.h b/Usermode/include/axwin/axwin.h
new file mode 100644 (file)
index 0000000..ee160b8
--- /dev/null
@@ -0,0 +1,37 @@
+/**
+ * \file axwin.h
+ * \author John Hodge (thePowersGang)
+ * \brief AxWin Core functions
+ */
+#ifndef _AXWIN_AXWIN_H
+#define _AXWIN_AXWIN_H
+
+// === Core Types ===
+typedef unsigned int   tAxWin_Handle;
+
+// === Messaging ===
+#include "messages.h"
+extern int     AxWin_MessageLoop();
+
+// === Window Control ===
+/**
+ * \brief Window Type
+ * \note Opaque Type
+ */
+typedef struct sAxWin_Window   tAxWin_Window;
+
+typedef int    tAxWin_MessageCallback(tAxWin_Message *);
+
+/**
+ * \brief Window Flags
+ * \{
+ */
+#define WINFLAG_NOBORDER       0x100
+/**
+ * \}
+ */
+extern tAxWin_Window   AxWin_CreateWindow(
+               int16_t X, int16_t Y, int16_t W, int16_t H,
+               uint32_t Flags, tAxWin_MessageCallback *Callback);
+
+#endif
index e4ed1fe..b27583e 100644 (file)
@@ -18,10 +18,23 @@ enum eAxWin_Messages
        // Server Requests
        MSG_SREQ_PING,
        // - Windows
-       MSG_SREQ_NEWWINDOW,     // (short x, y, w, h, uint32_t flags)
-       MSG_SREQ_GETFLAGS,      MSG_SREQ_SETFLAGS,
-       MSG_SREQ_GETRECT,       MSG_SREQ_SETRECT,
+       MSG_SREQ_REGISTER,      // bool (char[] Name) - Registers this PID with the Window Manager
+       
+       MSG_SREQ_ADDTAB,        // ELEMENT (char[] Name) - Adds a tab to the window
+       MSG_SREQ_DELTAB,        // void (TAB Tab)       - Closes a tab
+       
+       MSG_SREQ_NEWDIALOG,     // ELEMENT (ELEMENT Parent, char[] Name)        - Creates a dialog
+       MSG_SREQ_DELDIALOG,     // void (ELEMENT Dialog)        - Closes a dialog
+       
+       MSG_SREQ_SETNAME,       // void (ELEMENT Element, char[] Name)
+       MSG_SREQ_GETNAME,       // char[] (ELEMENT Element)
+       
+       // - Builtin Elements
+       MSG_SREQ_INSERT,        // void (ELEMENT Parent, eAxWin_Controls Type, u32 Flags)
+       
        // - Drawing
+       //  All drawing functions take an ELEMENT as their first parameter.
+       //  This must be either a Tab, Dialog or Canvas control
        MSG_SREQ_SETCOL,
        MSG_SREQ_PSET,
        MSG_SREQ_LINE,  MSG_SREQ_CURVE,
@@ -30,9 +43,7 @@ enum eAxWin_Messages
        MSG_SREQ_SETFONT,       MSG_SREQ_PUTTEXT,
        
        // Server Responses
-       MSG_SRSP_PONG,
-       MSG_SRSP_WINDOW,        // Returns the new window ID
-       MSG_SRSP_IMG,   // Returns the image ID
+       MSG_SRSP_RETURN,        // {int RequestID, void[] Return Value} - Returns a value from a server request
        
        NUM_MSG
 };
diff --git a/Usermode/include/readline.h b/Usermode/include/readline.h
new file mode 100644 (file)
index 0000000..831bb53
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Acess2 Library Suite
+ * - Readline
+ * 
+ * Text mode entry with history
+ */
+#ifndef _READLINE_H_
+#define _READLINE_H_
+
+// === TYPES ===
+typedef struct sReadline       tReadline;
+
+// === STRUCTURES ===
+struct sReadline
+{
+        int    UseHistory;     // Boolean
+       
+        int    NumHistory;
+       char    **History;
+};
+
+// === FUNCTIONS ===
+/**
+ * \brief Read a line from stdin
+ */
+extern char    *Readline(tReadline *Info);
+
+#endif

UCC git Repository :: git.ucc.asn.au