--- /dev/null
+ Copyright (c) 2009 John Hodge (thePowersGang)
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+ 3. This notice may not be removed or altered from any source
+ distribution.
+
include/binary.h \
include/modules.h \
include/vfs.h include/vfs_ext.h \
- include/fs_devfs.h \
+ include/fs_devfs.h include/fs_sysfs.h \
include/iocache.h \
include/apidoc/arch_x86.h \
include/tpl_drv_common.h \
- include/tpl_drv_video.h
+ include/tpl_drv_video.h \
+ include/tpl_drv_terminal.h \
+ include/tpl_drv_disk.h \
+ include/tpl_drv_keyboard.h \
+ include/tpl_drv_network.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
CFLAGS += -g
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 logging.o
+OBJ := $(addprefix arch/$(ARCHDIR)/,$(A_OBJ))
+OBJ += heap.o drvutil.o logging.o debug.o lib.o adt.o
+OBJ += messages.o modules.o syscalls.o system.o threads.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
-BUILD_NUM = 1822
+BUILD_NUM = 2145
--- /dev/null
+/*
+ */
+#include <acess.h>
+#include <adt.h>
+
+// === CODE ===
+// --- Ring Buffers ---
+tRingBuffer *RingBuffer_Create(size_t Space)
+{
+ tRingBuffer *ret = malloc(sizeof(tRingBuffer)+Space);
+ ret->Start = 0;
+ ret->Length = 0;
+ ret->Space = Space;
+ return ret;
+}
+
+size_t RingBuffer_Read(void *Dest, tRingBuffer *Buffer, size_t Length)
+{
+ if(Length > Buffer->Length) Length = Buffer->Length;
+
+ if( Buffer->Start + Length > Buffer->Space )
+ {
+ int endData = Buffer->Space - Buffer->Start;
+ memcpy(Dest, &Buffer->Data[Buffer->Start], endData);
+ memcpy(Dest + endData, &Buffer->Data, Length - endData);
+ }
+ else
+ {
+ memcpy(Dest, &Buffer->Data[Buffer->Start], Length);
+ }
+ Buffer->Length -= Length;
+ return Length;
+}
+
+size_t RingBuffer_Write(tRingBuffer *Buffer, void *Source, size_t Length)
+{
+ size_t bufEnd = Buffer->Start + Buffer->Length;
+ size_t endSpace = Buffer->Space - bufEnd;
+
+ // Force to bounds
+ if(Length > Buffer->Space - Buffer->Length)
+ Length = Buffer->Space - Buffer->Length;
+
+ if(endSpace < Length)
+ {
+ memcpy( &Buffer->Data[bufEnd], Source, endSpace );
+ memcpy( Buffer->Data, Source + endSpace, Length - endSpace );
+ Buffer->Length = Length - endSpace;
+ }
+ else
+ {
+ memcpy( &Buffer->Data[bufEnd], Source, Length );
+ Buffer->Length += Length;
+ }
+
+ return Length;
+}
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 vm8086.o
-#A_OBJ += gdb_stub.o
+A_OBJ += proc.o proc.ao time.o vm8086.o
+A_OBJ += kpanic.o
; IRQs
; - Timer
[global Isr240]
+[extern SchedulerBase]
Isr240:
push 0
jmp SchedulerBase
popa
add esp, 8 ; Error Code and ID
iret
-
-; --------------
-; Task Scheduler
-; --------------
-[extern Proc_Scheduler]
-SchedulerBase:
- pusha
- push ds
- push es
- 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
-
- call Proc_Scheduler
-
- add esp, 4 ; Remove Argument
-
- pop gs
- pop fs
- pop es
- pop ds
-
- mov dx, 0x20
- mov al, 0x20
- out dx, al ; ACK IRQ
- popa
- add esp, 4 ; CPU ID
- ; No Error code / int num
- iret
// === IMPORTS ===
extern void MM_PageFault(Uint Addr, Uint ErrorCode, tRegs *Regs);
extern void VM8086_GPF(tRegs *Regs);
-extern void Threads_Dump();
+extern void Threads_Dump(void);
+extern void Threads_Fault(int Num);
// === PROTOTYPES ===
void Error_Backtrace(Uint eip, Uint ebp);
return ;
}
+ // Check if it's a user mode fault
+ if( Regs->eip < KERNEL_BASE || (Regs->cs & 3) == 3 ) {
+ Log_Warning("Arch", "User Fault - %s, Code: 0x%x",
+ csaERROR_NAMES[Regs->int_num], Regs->err_code);
+ Log_Warning("Arch", "at CS:EIP %04x:%08x",
+ Regs->cs, Regs->eip);
+ switch( Regs->int_num )
+ {
+ // Division by Zero
+ case 0: Threads_Fault(FAULT_DIV0); break;
+ // Invalid opcode
+ case 6: Threads_Fault(FAULT_OPCODE); break;
+ // GPF
+ case 13: Threads_Fault(FAULT_ACCESS); break;
+ // Floating Point Exception
+ case 16: Threads_Fault(FAULT_FLOAT); break;
+
+ default: Threads_Fault(FAULT_MISC); break;
+ }
+ return ;
+ }
+
+ Debug_KernelPanic();
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);
if(Regs->cs == 0x08)
- Warning(" SS:ESP = 0x0010:%08x", 0x10, (Uint)Regs+sizeof(tRegs));
+ Warning(" SS:ESP = 0x0010:%08x", (Uint)Regs+sizeof(tRegs));
else
Warning(" SS:ESP = 0x%04x:%08x", Regs->ss, Regs->esp);
Warning(" EFLAGS = 0x%08x", Regs->eflags);
--- /dev/null
+/*
+ * Acess 2 Kernel
+ * By John Hodge (thePowersGang)
+ * - x86 Kernel Panic Handler
+ */
+
+#include <acess.h>
+
+#define FB ((Uint16 *)(KERNEL_BASE|0xB8000))
+#define BGC 0x4F00 // White on Red
+//#define BGC 0xC000 // Black on Bright Red
+//#define BGC 0x1F00 // White on Blue (BSOD!)
+
+ int giKP_Pos = 0;
+
+const struct {
+ Uint16 IdxPort;
+ Uint16 DatPort;
+ Uint8 Index;
+ Uint8 Value;
+} caRegValues[] = {
+ //{0x3C0, 0x3C0, 0x10, 0x0C}, // Mode Control (Blink Enabled)
+ {0x3C0, 0x3C0, 0x10, 0x04}, // Mode Control (Blink Disabled)
+ {0x3C0, 0x3C0, 0x11, 0x00}, // Overscan Register
+ {0x3C0, 0x3C0, 0x12, 0x0F}, // Color Plane Enable
+ {0x3C0, 0x3C0, 0x13, 0x08}, // Horizontal Panning
+ {0x3C0, 0x3C0, 0x14, 0x00}, // Color Select
+ {0 , 0x3C2, 0 , 0x67}, // Miscellaneous Output Register
+ {0x3C4, 0x3C5, 0x01, 0x00}, // Clock Mode Register
+ {0x3C4, 0x3C5, 0x03, 0x00}, // Character select
+ {0x3C4, 0x3C5, 0x04, 0x07}, // Memory Mode Register
+ {0x3CE, 0x3CF, 0x05, 0x10}, // Mode Register
+ {0x3CE, 0x3CF, 0x06, 0x0E}, // Miscellaneous Register
+ {0x3D4, 0x3D5, 0x00, 0x5F}, // Horizontal Total
+ {0x3D4, 0x3D5, 0x01, 0x4F}, // Horizontal Display Enable End
+ {0x3D4, 0x3D5, 0x02, 0x50}, // Horizontal Blank Start
+ {0x3D4, 0x3D5, 0x03, 0x82}, // Horizontal Blank End
+ {0x3D4, 0x3D5, 0x04, 0x55}, // Horizontal Retrace Start
+ {0x3D4, 0x3D5, 0x05, 0x81}, // Horizontal Retrace End
+ {0x3D4, 0x3D5, 0x06, 0xBF}, // Vertical Total
+ {0x3D4, 0x3D5, 0x07, 0x1F}, // Overflow Register
+ {0x3D4, 0x3D5, 0x08, 0x00}, // Preset row scan
+ {0x3D4, 0x3D5, 0x09, 0x4F}, // Maximum Scan Line
+ {0x3D4, 0x3D5, 0x10, 0x9C}, // Vertical Retrace Start
+ {0x3D4, 0x3D5, 0x11, 0x8E}, // Vertical Retrace End
+ {0x3D4, 0x3D5, 0x12, 0x8F}, // Vertical Display Enable End
+ {0x3D4, 0x3D5, 0x13, 0x28}, // Logical Width
+ {0x3D4, 0x3D5, 0x14, 0x1F}, // Underline Location
+ {0x3D4, 0x3D5, 0x15, 0x96}, // Vertical Blank Start
+ {0x3D4, 0x3D5, 0x16, 0xB9}, // Vertical Blank End
+ {0x3D4, 0x3D5, 0x17, 0xA3} // CRTC Mode Control
+};
+#define NUM_REGVALUES (sizeof(caRegValues)/sizeof(caRegValues[0]))
+
+/**
+ * \brief Sets the screen mode for a kernel panic
+ */
+void KernelPanic_SetMode()
+{
+ int i;
+
+ // This function is called by Panic(), but MM_PageFault and the
+ // CPU exception handers also call it, so let's not clear the screen
+ // twice
+ if( giKP_Pos ) return ;
+
+ // Restore VGA 0xB8000 text mode
+ #if 1
+ for( i = 0; i < NUM_REGVALUES; i++ )
+ {
+ // Reset Flip-Flop
+ if( caRegValues[i].IdxPort == 0x3C0 ) inb(0x3DA);
+
+ if( caRegValues[i].IdxPort )
+ outb(caRegValues[i].IdxPort, caRegValues[i].Index);
+ outb(caRegValues[i].DatPort, caRegValues[i].Value);
+ }
+
+ inb(0x3DA);
+ outb(0x3C0, 0x20);
+ #endif
+
+ // Clear Screen
+ for( i = 0; i < 80*25; i++ )
+ {
+ FB[i] = BGC;
+ }
+}
+
+void KernelPanic_PutChar(char Ch)
+{
+ if( giKP_Pos > 80*25 ) return ;
+ switch(Ch)
+ {
+ case '\t':
+ do {
+ FB[giKP_Pos] &= 0xFF00;
+ FB[giKP_Pos++] |= ' ';
+ } while(giKP_Pos & 7);
+ break;
+
+ case '\n':
+ giKP_Pos += 80;
+ case '\r':
+ giKP_Pos -= giKP_Pos % 80;
+ break;
+
+ default:
+ if(' ' <= Ch && Ch < 0x7F)
+ {
+ FB[giKP_Pos] &= 0xFF00;
+ FB[giKP_Pos] |= Ch;
+ }
+ giKP_Pos ++;
+ break;
+ }
+}
_UsertextBase = .;
*(.usertext)
}
+ _UsertextEnd = .;
.rodata ALIGN(0x1000): AT(ADDR(.rodata) - 0xC0000000) {
*(.initpd)
extern Uint Proc_Clone(Uint *Err, Uint Flags);
extern void Threads_Sleep(void);
extern void Threads_Exit(void);
+// --- Core ---
+extern void System_Init(char *Commandline);
-extern int Modules_LoadBuiltins(void);
+// === PROTOTYPES ===
+void Arch_LoadBootModules(void);
// === GLOBALS ===
char *gsBootCmdLine = NULL;
+struct {
+ void *Base;
+ Uint Size;
+ char *ArgString;
+} *gaArch_BootModules;
+ int giArch_NumBootModules = 0;
// === CODE ===
int kmain(Uint MbMagic, void *MbInfoPtr)
// Load Virtual Filesystem
VFS_Init();
- // 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 );
+ giArch_NumBootModules = mbInfo->ModuleCount;
+ gaArch_BootModules = malloc( giArch_NumBootModules * sizeof(*gaArch_BootModules) );
for( i = 0; i < mbInfo->ModuleCount; i ++ )
{
// Adjust into higher half
- mods[i].Start += KERNEL_BASE;
- mods[i].End += KERNEL_BASE;
+ mods[i].Start += KERNEL_BASE;
+ mods[i].End += KERNEL_BASE;
mods[i].String += KERNEL_BASE;
- 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 ) )
- {
- Log_Warning("Arch", "Unable to load module\n");
- }
+ gaArch_BootModules[i].Base = (void *)mods[i].Start;
+ gaArch_BootModules[i].Size = mods[i].End - mods[i].Start;
+ gaArch_BootModules[i].ArgString = (char *)mods[i].String;
}
// Pass on to Independent Loader
Log_Log("Arch", "Starting system");
- System_Init( gsBootCmdLine );
+ System_Init(gsBootCmdLine);
// Sleep forever (sleeping beauty)
for(;;)
Threads_Sleep();
return 0;
}
+
+void Arch_LoadBootModules(void)
+{
+ int i;
+ for( i = 0; i < giArch_NumBootModules; i ++ )
+ {
+ Log_Log("Arch", "Loading '%s'", gaArch_BootModules[i].ArgString);
+
+ if( !Module_LoadMem( gaArch_BootModules[i].Base, gaArch_BootModules[i].Size, gaArch_BootModules[i].ArgString ) )
+ {
+ Log_Warning("Arch", "Unable to load module\n");
+ }
+ }
+ Log_Log("Arch", "Boot modules loaded");
+ free( gaArch_BootModules );
+}
#endif
// === IMPORTS ===
+extern void _UsertextEnd, _UsertextBase;
extern Uint32 gaInitPageDir[1024];
extern Uint32 gaInitPageTable[1024];
extern void Threads_SegFault(tVAddr Addr);
memset( &gaPageTable[i*1024], 0, 0x1000 );
}
#endif
+
+ // Unset kernel on the User Text pages
+ for( i = ((tVAddr)&_UsertextEnd-(tVAddr)&_UsertextBase+0xFFF)/4096; i--; ) {
+ Log("MM_SetFlags( 0x%08x, 0, MM_PFLAG_KERNEL)", (tVAddr)&_UsertextBase + i*4096);
+ MM_SetFlags( (tVAddr)&_UsertextBase + i*4096, 0, MM_PFLAG_KERNEL );
+ }
}
/**
return ;
}
+ Debug_KernelPanic();
+
// -- Check Error Code --
if(ErrorCode & 8)
Warning("Reserved Bits Trashed!");
// Read-Only
if( Mask & MM_PFLAG_RO )
{
- if( Flags & MM_PFLAG_RO ) *ent &= ~PF_WRITE;
- else *ent |= PF_WRITE;
+ if( Flags & MM_PFLAG_RO ) {
+ *ent &= ~PF_WRITE;
+ }
+ else {
+ gaPageDir[VAddr >> 22] |= PF_WRITE;
+ *ent |= PF_WRITE;
+ }
}
// Kernel
if( Mask & MM_PFLAG_KERNEL )
{
- if( Flags & MM_PFLAG_KERNEL ) *ent &= ~PF_USER;
- else *ent |= PF_USER;
+ if( Flags & MM_PFLAG_KERNEL ) {
+ *ent &= ~PF_USER;
+ }
+ else {
+ gaPageDir[VAddr >> 22] |= PF_USER;
+ *ent |= PF_USER;
+ }
}
// Copy-On-Write
*ent |= PF_WRITE;
}
}
+
+ //Log("MM_SetFlags: *ent = 0x%08x, gaPageDir[%i] = 0x%08x",
+ // *ent, VAddr >> 22, gaPageDir[VAddr >> 22]);
}
/**
void MM_UnmapHWPages(tVAddr VAddr, Uint Number)
{
int i, j;
+
+ //Log_Debug("VirtMem", "MM_UnmapHWPages: (VAddr=0x%08x, Number=%i)", VAddr, Number);
+
// Sanity Check
- if(VAddr < HW_MAP_ADDR || VAddr-Number*0x1000 > HW_MAP_MAX) return;
+ if(VAddr < HW_MAP_ADDR || VAddr+Number*0x1000 > HW_MAP_MAX) return;
i = VAddr >> 12;
LOCK( &gilTempMappings ); // Temp and HW share a directory, so they share a lock
+
for( j = 0; j < Number; j++ )
{
- MM_DerefPhys( gaPageTable[ (HW_MAP_ADDR >> 12) + i + j ] );
- gaPageTable[ (HW_MAP_ADDR >> 12) + i + j ] = 0;
+ MM_DerefPhys( gaPageTable[ i + j ] & ~0xFFF );
+ gaPageTable[ i + j ] = 0;
}
RELEASE( &gilTempMappings );
--- /dev/null
+; AcessOS Microkernel Version
+; Start.asm
+
+[bits 32]
+
+KERNEL_BASE equ 0xC0000000
+
+KSTACK_USERSTATE_SIZE equ (4+8+1+5)*4 ; SRegs, GPRegs, CPU, IRET
+
+[section .text]
+; --------------
+; Task Scheduler
+; --------------
+[extern Proc_Scheduler]
+[global SchedulerBase]
+SchedulerBase:
+ pusha
+ push ds
+ push es
+ 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
+
+ call Proc_Scheduler
+
+ add esp, 4 ; Remove Argument
+
+ pop gs
+ pop fs
+ pop es
+ pop ds
+
+ mov dx, 0x20
+ mov al, 0x20
+ out dx, al ; ACK IRQ
+ popa
+ add esp, 4 ; CPU ID
+ ; No Error code / int num
+ iret
+
+[extern Proc_Clone]
+[extern Threads_Exit]
+[global SpawnTask]
+SpawnTask:
+ ; Call Proc_Clone with Flags=0
+ xor eax, eax
+ push eax
+ push eax
+ call Proc_Clone
+ add esp, 8 ; Remove arguments from stack
+
+ test eax, eax
+ jnz .parent
+
+ ; In child, so now set up stack frame
+ mov ebx, [esp+4] ; Child Function
+ mov edx, [esp+8] ; Argument
+ ; Child
+ push edx ; Argument
+ call ebx ; Function
+ call Threads_Exit ; Kill Thread
+
+.parent:
+ ret
+
+;
+; Calls a user fault handler
+;
+[global Proc_AlterUserReturnAddr]
+[extern Proc_GetCurThread]
+Proc_AlterUserReturnAddr:
+ ; EBP is the handler to use
+
+ call Proc_GetCurThread
+ xchg bx, bx
+
+ ; EAX is the current thread
+ mov ebx, eax
+ mov eax, [ebx+40] ; Get Kernel Stack
+ sub eax, KSTACK_USERSTATE_SIZE
+
+ ;
+ ; NOTE: This can cause corruption if the signal happens while the user
+ ; has called a kernel operation.
+ ; Good thing this can only be called on a user fault.
+ ;
+
+ ; Get and alter User SP
+ mov ecx, [eax+KSTACK_USERSTATE_SIZE-12]
+ mov edx, [ebx+60] ; Get Signal Number
+ mov [ecx-4], edx
+ mov [ecx-8], DWORD User_Syscall_RetAndExit
+ sub ecx, 8
+
+ ; Restore Segment Registers
+ mov ax, 0x23
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+
+ push 0x23 ; SS
+ push ecx ; ESP
+ push 0x202 ; EFLAGS (IP and Rsvd)
+ push 0x1B ; CS
+ push ebp ; EIP
+
+ iret
+
+
+[section .usertext]
+User_Syscall_RetAndExit:
+ push eax
+ call User_Syscall_Exit
+User_Syscall_Exit:
+ xor eax, eax
+ mov ebx, [esp+4]
+ int 0xAC
extern void Threads_Dump();
extern tThread *Threads_CloneTCB(Uint *Err, Uint Flags);
extern void Isr8(); // Double Fault
+extern void Proc_AlterUserReturnAddr();
// === PROTOTYPES ===
void ArchThreads_Init();
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_CallFaultHandler(tThread *Thread);
void Proc_Scheduler();
// === GLOBALS ===
return 0;
}
+/**
+ * \brief Calls a signal handler in user mode
+ * \note Used for signals
+ */
+void Proc_CallFaultHandler(tThread *Thread)
+{
+ // Rewinds the stack and calls the user function
+ // Never returns
+ __asm__ __volatile__ ("mov %0, %%ebp;\n\tcall Proc_AlterUserReturnAddr" :: "r"(Thread->FaultHandler));
+ for(;;);
+}
+
/**
* \fn void Proc_Scheduler(int CPU)
* \brief Swap current thread and clears dead threads
#else
__asm__ __volatile__ ("mov %0, %%cr3"::"a"(thread->MemState.CR3));
#endif
+
+ #if 0
+ if(thread->SavedState.ESP > 0xC0000000
+ && thread->SavedState.ESP < thread->KernelStack-0x2000) {
+ Log_Warning("Proc", "Possible bad ESP %p (PID %i)", thread->SavedState.ESP);
+ }
+ #endif
+
// Switch threads
__asm__ __volatile__ (
"mov %1, %%esp\n\t" // Restore ESP
pop ebp\r
ret\r
\r
-[extern Proc_Clone]\r
-[extern Threads_Exit]\r
-[global SpawnTask]\r
-SpawnTask:\r
- ; Call Proc_Clone with Flags=0\r
- xor eax, eax\r
- push eax
- push eax\r
- call Proc_Clone\r
- add esp, 8 ; Remove arguments from stack\r
- \r
- test eax, eax\r
- jnz .parent\r
- \r
- ; In child, so now set up stack frame\r
- mov ebx, [esp+4] ; Child Function\r
- mov edx, [esp+8] ; Argument\r
- ; Child\r
- push edx ; Argument\r
- call ebx ; Function\r
- call Threads_Exit ; Kill Thread\r
- \r
-.parent:\r
- ret\r
-\r
[section .initpd]\r
[global gaInitPageDir]\r
[global gaInitPageTable]\r
// === MACROS ===
#define NUM_TIMERS 8
#define TIMER_QUANTUM 100
-#define TIMER_RATE 13 // (Max: 15, Min: 2) - 15 = 1Hz, 13 = 4Hz, 10 = 1024Hz
-#define TIMER_FREQ (32768>>TIMER_RATE) //Hz
+// 2^(15-rate), 15: 1HZ, 5: 1024Hz, 2: 8192Hz
+#define TIMER_RATE 12 // (Max: 15, Min: 2) - 15 = 1Hz, 13 = 4Hz, 12 = 8Hz, 11 = 16Hz 10 = 32Hz, 2
+#define TIMER_FREQ (0x8000>>TIMER_RATE) //Hz
#define MS_PER_TICK_WHOLE (1000/(TIMER_FREQ))
#define MS_PER_TICK_FRACT ((Uint64)(1000*TIMER_FREQ-((Uint64)MS_PER_TICK_WHOLE)*0x80000000/TIMER_FREQ))
#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
+ 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,
+ VM8086_OP_OUT_AD = 0xEE,
+ VM8086_OP_OUT_ADX = 0xEF
};
#define VM8086_PAGES_PER_INST 4
tSpinlock glVM8086_Process;
tPID gVM8086_WorkerPID;
tTID gVM8086_CallingThread;
-tVM8086 * volatile gpVM8086_State;
+tVM8086 * volatile gpVM8086_State = (void*)-1; // Set to -1 to avoid race conditions
// === FUNCTIONS ===
int VM8086_Install(char **Arguments)
{
tPID pid;
+ // Lock to avoid race conditions
+ LOCK( &glVM8086_Process );
+
// Create BIOS Call process
pid = Proc_Clone(NULL, CLONE_VM);
if(pid == -1)
if(Regs->eip == VM8086_MAGIC_IP && Regs->cs == VM8086_MAGIC_CS
&& Threads_GetPID() == gVM8086_WorkerPID)
{
+ if( gpVM8086_State == (void*)-1 ) {
+ Log_Log("VM8086", "Worker thread ready and waiting");
+ RELEASE( &glVM8086_Process ); // Release lock obtained in VM8086_Install
+ gpVM8086_State = NULL;
+ }
if( gpVM8086_State ) {
gpVM8086_State->AX = Regs->eax; gpVM8086_State->CX = Regs->ecx;
gpVM8086_State->DX = Regs->edx; gpVM8086_State->BX = Regs->ebx;
return ;
}
- opcode = *(Uint8*)( KERNEL_BASE + (Regs->cs*16) + (Regs->eip) );
+ opcode = *(Uint8*)( (Regs->cs*16) + (Regs->eip) );
Regs->eip ++;
switch(opcode)
{
#endif
break;
- case 0xEE: //OUT DX, AL
+ case VM8086_OP_OUT_AD: //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
+ case VM8086_OP_OUT_ADX: //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);
break;
case 0x66:
- Log_Warning("VM8086", "Code at %04x:%04x attempted to use an operand override, ignored",
- Regs->cs, Regs->eip);
+ opcode = *(Uint8*)( (Regs->cs*16) + (Regs->eip&0xFFFF));
+ switch( opcode )
+ {
+ case VM8086_OP_IN_ADX: //IN AX, DX
+ Regs->eax = ind(Regs->edx&0xFFFF);
+ #if TRACE_EMU
+ Log_Debug("VM8086", "Emulated IN EAX, DX (Port 0x%x)\n", Regs->edx&0xFFFF);
+ #endif
+ break;
+ case VM8086_OP_OUT_ADX: //OUT DX, AX
+ outd(Regs->edx&0xFFFF, Regs->eax);
+ #if TRACE_EMU
+ Log_Debug("VM8086", "Emulated OUT DX, EAX (*0x%04x = 0x%08x)\n", Regs->edx&0xFFFF, Regs->eax);
+ #endif
+ break;
+ default:
+ Log_Error("VM8086", "Error - Unknown opcode 66 %02x caused a GPF at %04x:%04x",
+ Regs->cs, Regs->eip,
+ opcode
+ );
+ // Force an end to the call
+ Regs->cs = VM8086_MAGIC_CS;
+ Regs->eip = VM8086_MAGIC_IP;
+ break;
+ }
break;
default:
#define DEBUG_TO_SERIAL 1
#define SERIAL_PORT 0x3F8
#define GDB_SERIAL_PORT 0x2F8
+#define DEBUG_USE_VSNPRINTF 1
+#define DEBUG_MAX_LINE_LEN 256
// === IMPORTS ===
-extern void Threads_Dump();
+extern void Threads_Dump(void);
+extern void KernelPanic_SetMode(void);
+extern void KernelPanic_PutChar(char Ch);
+
+// === PROTOTYPES ===
+ int putDebugChar(char ch);
+ int getDebugChar();
+static void Debug_Putchar(char ch);
+static void Debug_Puts(char *Str);
+void Debug_Fmt(const char *format, va_list args);
// === GLOBALS ===
int gDebug_Level = 0;
int giDebug_KTerm = -1;
int gbDebug_SerialSetup = 0;
int gbGDB_SerialSetup = 0;
+ int gbDebug_IsKPanic = 0;
+volatile int gbInPutChar = 0;
// === CODE ===
int putDebugChar(char ch)
static void Debug_Putchar(char ch)
{
- if(giDebug_KTerm != -1)
- VFS_Write(giDebug_KTerm, 1, &ch);
-
+ #if DEBUG_TO_E9
+ __asm__ __volatile__ ( "outb %%al, $0xe9" :: "a"(((Uint8)ch)) );
+ #endif
+
#if DEBUG_TO_SERIAL
if(!gbDebug_SerialSetup) {
outb(SERIAL_PORT + 1, 0x00); // Disable all interrupts
while( (inb(SERIAL_PORT + 5) & 0x20) == 0 );
outb(SERIAL_PORT, ch);
#endif
-
- #if DEBUG_TO_E9
- __asm__ __volatile__ ( "outb %%al, $0xe9" :: "a"(((Uint8)ch)) );
- #endif
+
+ if( !gbDebug_IsKPanic )
+ {
+ if(gbInPutChar) return ;
+ gbInPutChar = 1;
+ if(giDebug_KTerm != -1)
+ VFS_Write(giDebug_KTerm, 1, &ch);
+ gbInPutChar = 0;
+ }
+ else
+ KernelPanic_PutChar(ch);
}
static void Debug_Puts(char *Str)
{
- while(*Str) Debug_Putchar(*Str++);
+ int len = 0;
+ while( *Str )
+ {
+ #if DEBUG_TO_E9
+ __asm__ __volatile__ ( "outb %%al, $0xe9" :: "a" ((Uint8)*Str) );
+ #endif
+
+ #if DEBUG_TO_SERIAL
+ if(!gbDebug_SerialSetup) {
+ outb(SERIAL_PORT + 1, 0x00); // Disable all interrupts
+ outb(SERIAL_PORT + 3, 0x80); // Enable DLAB (set baud rate divisor)
+ outb(SERIAL_PORT + 0, 0x03); // Set divisor to 3 (lo byte) 38400 baud
+ outb(SERIAL_PORT + 1, 0x00); // (hi byte)
+ outb(SERIAL_PORT + 3, 0x03); // 8 bits, no parity, one stop bit
+ outb(SERIAL_PORT + 2, 0xC7); // Enable FIFO with 14-byte threshold and clear it
+ outb(SERIAL_PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set
+ gbDebug_SerialSetup = 1;
+ }
+ while( (inb(SERIAL_PORT + 5) & 0x20) == 0 );
+ outb(SERIAL_PORT, *Str);
+ #endif
+
+ if( gbDebug_IsKPanic )
+ KernelPanic_PutChar(*Str);
+ len ++;
+ Str ++;
+ }
+
+ Str -= len;
+
+ if( !gbDebug_IsKPanic && giDebug_KTerm != -1)
+ {
+ if(gbInPutChar) return ;
+ gbInPutChar = 1;
+ VFS_Write(giDebug_KTerm, len, Str);
+ gbInPutChar = 0;
+ }
}
-void Debug_Fmt(const char *format, va_list *args)
+void Debug_Fmt(const char *format, va_list args)
{
+ #if DEBUG_USE_VSNPRINTF
+ char buf[DEBUG_MAX_LINE_LEN];
+ int len;
+ len = vsnprintf(buf, DEBUG_MAX_LINE_LEN-1, format, args);
+ //if( len < DEBUG_MAX_LINE )
+ // do something
+ Debug_Puts(buf);
+ return ;
+ #else
char c, pad = ' ';
int minSize = 0, len;
char tmpBuf[34]; // For Integers
break;
}
}
+ #endif
+}
+
+void Debug_KernelPanic()
+{
+ gbDebug_IsKPanic = 1;
+ KernelPanic_SetMode();
}
/**
va_start(args, Fmt);
- Debug_Fmt(Fmt, &args);
+ Debug_Fmt(Fmt, args);
va_end(args);
}
Debug_Puts("Log: ");
va_start(args, Fmt);
- Debug_Fmt(Fmt, &args);
+ Debug_Fmt(Fmt, args);
va_end(args);
Debug_Putchar('\n');
}
va_list args;
Debug_Puts("Warning: ");
va_start(args, Fmt);
- Debug_Fmt(Fmt, &args);
+ Debug_Fmt(Fmt, args);
va_end(args);
Debug_Putchar('\n');
}
void Panic(char *Fmt, ...)
{
va_list args;
+
+ Debug_KernelPanic();
+
Debug_Puts("Panic: ");
va_start(args, Fmt);
- Debug_Fmt(Fmt, &args);
+ Debug_Fmt(Fmt, args);
va_end(args);
Debug_Putchar('\n');
void Debug_SetKTerminal(char *File)
{
- if(giDebug_KTerm != -1)
- VFS_Close(giDebug_KTerm);
- giDebug_KTerm = VFS_Open(File, VFS_OPENFLAG_WRITE);
- Log_Log("Debug", "Opened '%s' as 0x%x", File, giDebug_KTerm);
+ int tmp;
+ if(giDebug_KTerm != -1) {
+ tmp = giDebug_KTerm;
+ giDebug_KTerm = -1;
+ VFS_Close(tmp);
+ }
+ tmp = VFS_Open(File, VFS_OPENFLAG_WRITE);
+ Log_Log("Debug", "Opened '%s' as 0x%x", File, tmp);
+ giDebug_KTerm = tmp;
+ Log_Log("Debug", "Returning to %p", __builtin_return_address(0));
}
void Debug_Enter(char *FuncName, char *ArgTypes, ...)
if(pos != -1) ArgTypes[pos] = ' ';
switch(*ArgTypes)
{
- 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;
+ 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': Debug_Fmt("0x%llx", &args); break;
- case 'B': Debug_Fmt("0b%llb", &args); break;
+ case 'X': Debug_Fmt("0x%llx", args); break;
+ case 'B': Debug_Fmt("0b%llb", args); break;
}
if(pos != -1) {
Debug_Putchar(','); Debug_Putchar(' ');
while(i--) Debug_Putchar(' ');
Debug_Puts(FuncName); Debug_Puts(": ");
- Debug_Fmt(Fmt, &args);
+ Debug_Fmt(Fmt, args);
va_end(args);
Debug_Putchar('\n');
switch(RetType)
{
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;
+ 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': Debug_Fmt("0x%llx", &args); break;
+ case 'X': Debug_Fmt("0x%llx", args); break;
}
Debug_Putchar('\n');
{
switch(ch)
{
+ case 'q': *((int*)1) = 0; break;
case 'd': __asm__ __volatile__ ("xchg %bx, %bx"); break;
case 'p': Threads_Dump(); break;
}
/*
* Acess2 VGA Controller Driver
*/
+#define DEBUG 0
#include <acess.h>
#include <fs_devfs.h>
#include <tpl_drv_video.h>
/*
* Acess2 Virtual Terminal Driver
*/
-#define DEBUG 1
+#define DEBUG 0
#include <acess.h>
#include <fs_devfs.h>
#include <modules.h>
#define NUM_VTS 8
#define MAX_INPUT_CHARS32 64
#define MAX_INPUT_CHARS8 (MAX_INPUT_CHARS32*4)
-#define VT_SCROLLBACK 1 // 2 Screens of text
-#define DEFAULT_OUTPUT "VGA"
//#define DEFAULT_OUTPUT "BochsGA"
-//#define DEFAULT_OUTPUT "Vesa"
+#define DEFAULT_OUTPUT "Vesa"
#define DEFAULT_INPUT "PS2Keyboard"
-#define DEFAULT_WIDTH 80
-#define DEFAULT_HEIGHT 25
+#define DEFAULT_WIDTH 640
+#define DEFAULT_HEIGHT 480
+#define DEFAULT_SCROLLBACK 2 // 2 Screens of text + current screen
+#define TEXTTERM_WIDTH (BOOT_WIDTH/8)
+#define TEXTTERM_HEIGHT (BOOT_WIDTH/16)
#define DEFAULT_COLOUR (VT_COL_BLACK|(0xAAA<<16))
#define VT_FLAG_HIDECSR 0x01
// === PROTOTYPES ===
int VT_Install(char **Arguments);
+void VT_InitOutput(void);
+void VT_InitInput(void);
char *VT_ReadDir(tVFS_Node *Node, int Pos);
tVFS_Node *VT_FindDir(tVFS_Node *Node, char *Name);
int VT_Root_IOCtl(tVFS_Node *Node, int Id, void *Data);
Uint64 VT_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
Uint64 VT_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
int VT_Terminal_IOCtl(tVFS_Node *Node, int Id, void *Data);
+void VT_SetResolution(int Width, int Height);
+void VT_SetMode(int Mode);
void VT_SetTerminal(int ID);
void VT_KBCallBack(Uint32 Codepoint);
void VT_int_PutString(tVTerm *Term, Uint8 *Buffer, Uint Count);
int VT_int_ParseEscape(tVTerm *Term, char *Buffer);
void VT_int_PutChar(tVTerm *Term, Uint32 Ch);
+void VT_int_ScrollFramebuffer( tVTerm *Term );
void VT_int_UpdateScreen( tVTerm *Term, int UpdateAll );
void VT_int_ChangeMode(tVTerm *Term, int NewMode);
// === CONSTANTS ===
const Uint16 caVT100Colours[] = {
+ // Black, Red, Green, Yellow, Blue, Purple, Cyan, Gray
+ // Same again, but bright
VT_COL_BLACK, 0x700, 0x070, 0x770, 0x007, 0x707, 0x077, 0xAAA,
VT_COL_GREY, 0xF00, 0x0F0, 0xFF0, 0x00F, 0xF0F, 0x0FF, VT_COL_WHITE
};
// --- Terminals ---
tVTerm gVT_Terminals[NUM_VTS];
int giVT_CurrentTerminal = 0;
+tVTerm *gpVT_CurTerm = &gVT_Terminals[0];
// --- Video State ---
-short giVT_RealWidth; //!< Real Width
-short giVT_RealHeight; //!< Real Height
- int gbVT_TextMode = 1;
+short giVT_RealWidth = DEFAULT_WIDTH; //!< Screen Width
+short giVT_RealHeight = DEFAULT_HEIGHT; //!< Screen Height
+ int giVT_Scrollback = DEFAULT_SCROLLBACK;
// --- Driver Handles ---
char *gsVT_OutputDevice = NULL;
char *gsVT_InputDevice = NULL;
*/
int VT_Install(char **Arguments)
{
- char **args = Arguments;
- char *arg;
int i;
// Scan Arguments
if(Arguments)
{
+ char **args = Arguments;
+ char *arg, *opt, *val;
for( ; (arg = *args); args++ )
{
- if(arg[0] != '-') continue;
+ Log_Debug("VTerm", "Argument '%s'", arg);
+ opt = arg;
+ val = arg + strpos(arg, '='); *val++ = '\0';
- switch(arg[1])
- {
- // Set output device
- case 'o':
- if(args[1] == NULL) break;
+ if( strcmp(opt, "Video") == 0 ) {
if(gsVT_OutputDevice) free(gsVT_OutputDevice);
- gsVT_OutputDevice = malloc(strlen(args[1])+1);
- strcpy(gsVT_OutputDevice, args[1]);
- args ++;
- break;
-
- // Set input device
- case 'i':
- if(args[1] == NULL) break;
+ gsVT_OutputDevice = strdup(val);
+ }
+ else if( strcmp(opt, "Input") == 0 ) {
if(gsVT_InputDevice) free(gsVT_InputDevice);
- gsVT_InputDevice = malloc(strlen(args[1])+1);
- strcpy(gsVT_InputDevice, args[1]);
- args ++;
- break;
-
+ gsVT_InputDevice = strdup(val);
+ }
+ else if( strcmp(opt, "Width") == 0 ) {
+ giVT_RealWidth = atoi( val );
+ }
+ else if( strcmp(opt, "Height") == 0 ) {
+ giVT_RealHeight = atoi( val );
+ }
+ else if( strcmp(opt, "Scrollback") == 0 ) {
+ giVT_Scrollback = atoi( val );
}
}
}
{
gVT_Terminals[i].Mode = TERM_MODE_TEXT;
gVT_Terminals[i].Flags = 0;
- gVT_Terminals[i].Width = DEFAULT_WIDTH;
- gVT_Terminals[i].Height = DEFAULT_HEIGHT;
+ gVT_Terminals[i].Width = giVT_RealWidth/giVT_CharWidth;
+ gVT_Terminals[i].Height = giVT_RealHeight/giVT_CharHeight;
gVT_Terminals[i].CurColour = DEFAULT_COLOUR;
gVT_Terminals[i].WritePos = 0;
gVT_Terminals[i].ViewPos = 0;
- gVT_Terminals[i].Buffer = calloc( DEFAULT_WIDTH*DEFAULT_HEIGHT*VT_SCROLLBACK, sizeof(tVT_Char) );
+ gVT_Terminals[i].Buffer = calloc(
+ gVT_Terminals[i].Width*gVT_Terminals[i].Height*(giVT_Scrollback+1),
+ sizeof(tVT_Char)
+ );
gVT_Terminals[i].Name[0] = '0'+i;
gVT_Terminals[i].Name[1] = '\0';
// Add to DevFS
DevFS_AddDevice( &gVT_DrvInfo );
+ VT_InitOutput();
+ VT_InitInput();
+
// Set kernel output to VT0
Debug_SetKTerminal("/Devices/VTerm/0");
+ Log_Log("VTerm", "Returning %i", MODULE_ERR_OK);
return MODULE_ERR_OK;
}
void VT_InitOutput()
{
giVT_OutputDevHandle = VFS_Open(gsVT_OutputDevice, VFS_OPENFLAG_WRITE);
+ if(giVT_InputDevHandle == -1) {
+ Log_Warning("VTerm", "Oh F**k, I can't open the video device '%s'", gsVT_OutputDevice);
+ return ;
+ }
+ VT_SetResolution(giVT_RealWidth, giVT_RealHeight);
VT_SetTerminal( 0 );
+ VT_SetMode( VIDEO_BUFFMT_TEXT );
}
/**
{
int num;
- //ENTER("pNode sName", Node, Name);
+ ENTER("pNode sName", Node, Name);
// Open the input and output files if needed
if(giVT_OutputDevHandle == -2) VT_InitOutput();
return NULL;
}
// Return node
- //LEAVE('p', &gVT_Terminals[num].Node);
+ LEAVE('p', &gVT_Terminals[num].Node);
return &gVT_Terminals[num].Node;
}
}
break;
- case TERM_MODE_FB:
- //case TERM_MODE_:
+ //case TERM_MODE_FB:
+ default:
while(pos < Length)
{
while(term->InputRead == term->InputWrite) Threads_Yield();
Uint64 VT_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
{
tVTerm *term = &gVT_Terminals[ Node->Inode ];
-
- //ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);
+ int size;
// Write
switch( term->Mode )
VT_int_PutString(term, Buffer, Length);
break;
case TERM_MODE_FB:
- if( giVT_RealWidth > term->Width || giVT_RealHeight > term->Height )
+ size = term->Width*term->Height*4;
+ if( Offset > size ) {
+ Log_Notice("VTerm", "VT_Write: Offset (0x%llx) > FBSize (0x%x)",
+ Offset, size);
+ return 0;
+ }
+
+ if( Offset + Length > size ) {
+ Log_Notice("VTerm", "VT_Write: Offset+Length (0x%llx) > FBSize (0x%x)",
+ Offset+Length, size);
+ Length = size - Offset;
+ }
+
+ memcpy( (void*)((Uint)term->Buffer + (Uint)Offset), Buffer, Length );
+
+ if( Node->Inode == giVT_CurrentTerminal )
{
- #if 0
- int x, y, h;
- x = Offset/4; y = x / term->Width; x %= term->Width;
- w = Length/4+x; h = w / term->Width; w %= term->Width;
- while(h--)
+ if( giVT_RealWidth > term->Width || giVT_RealHeight > term->Height )
{
- VFS_WriteAt( giVT_OutputDevHandle,
- (x+y*term->RealWidth)*4,
- term->Width * 4,
- Buffer
- );
- Buffer = (void*)( (Uint)Buffer + term->Width*term->Height*4 );
+ int x, y, w, h;
+ x = Offset/4; y = x / term->Width; x %= term->Width;
+ w = Length/4+x; h = w / term->Width; w %= term->Width;
+ // Center
+ x += (giVT_RealWidth - term->Width) / 2;
+ y += (giVT_RealHeight - term->Height) / 2;
+ while(h--)
+ {
+ VFS_WriteAt( giVT_OutputDevHandle,
+ (x + y * giVT_RealWidth)*4,
+ term->Width * 4,
+ Buffer
+ );
+ Buffer = (void*)( (Uint)Buffer + term->Width*4 );
+ y ++;
+ }
+ return 0;
+ }
+ else {
+ return VFS_WriteAt( giVT_OutputDevHandle, Offset, Length, Buffer );
}
- #endif
- return 0;
}
- else {
- return VFS_WriteAt( giVT_OutputDevHandle, Offset, Length, Buffer );
+
+ case TERM_MODE_2DACCEL:
+ //case TERM_MODE_3DACCEL:
+ if( Node->Inode == giVT_CurrentTerminal )
+ {
+ VFS_Write( giVT_OutputDevHandle, Length, Buffer );
}
+ break;
}
- //LEAVE('i', 0);
return 0;
}
ENTER("pNode iId pData", Node, Id, Data);
if(Id >= DRV_IOCTL_LOOKUP) {
+ // Only root can fiddle with graphics modes
+ // TODO: Remove this and replace with user ownership
if( Threads_GetUID() != 0 ) return -1;
}
switch(Id)
{
+ // --- Core Defined
case DRV_IOCTL_TYPE:
LEAVE('i', DRV_TYPE_TERMINAL);
return DRV_TYPE_TERMINAL;
case TERM_IOCTL_MODETYPE:
if(Data != NULL)
{
+ if( CheckMem(Data, sizeof(int)) == 0 ) {
+ LEAVE('i', -1);
+ return -1;
+ }
+ Log_Log("VTerm", "VTerm %i mode set to %i", (int)Node->Inode, *iData);
+
+ // Update mode if needed
if(term->Mode != *iData)
VT_int_ChangeMode(term, *iData);
// Update the screen dimensions
- if(giVT_CurrentTerminal == Node->Inode)
+ if(Node->Inode == giVT_CurrentTerminal)
VT_SetTerminal( giVT_CurrentTerminal );
}
LEAVE('i', term->Mode);
// Get/set the terminal width
case TERM_IOCTL_WIDTH:
- if(Data != NULL) term->Width = *iData;
+ if(Data != NULL) {
+ if( CheckMem(Data, sizeof(int)) == 0 ) {
+ LEAVE('i', -1);
+ return -1;
+ }
+ term->Width = *iData;
+ }
Log("VT_Terminal_IOCtl - RETURN term->Width = %i", term->Width);
LEAVE('i', term->Width);
return term->Width;
// Get/set the terminal height
case TERM_IOCTL_HEIGHT:
- if(Data != NULL) term->Height = *iData;
+ if(Data != NULL) {
+ if( CheckMem(Data, sizeof(int)) == 0 ) {
+ LEAVE('i', -1);
+ return -1;
+ }
+ term->Height = *iData;
+ }
Log("VT_Terminal_IOCtl - RETURN term->Height = %i", term->Height);
LEAVE('i', term->Height);
return term->Height;
case TERM_IOCTL_FORCESHOW:
+ Log_Log("VTerm", "Thread %i forced VTerm %i to be shown",
+ Threads_GetTID(), (int)Node->Inode);
VT_SetTerminal( Node->Inode );
LEAVE('i', 1);
return 1;
return -1;
}
-void VT_SetResolution(int IsTextMode, int Width, int Height)
+void VT_SetResolution(int Width, int Height)
{
tVideo_IOCtl_Mode mode = {0};
int tmp;
+ int i;
// Create the video mode
mode.width = Width;
// Set video mode
VFS_IOCtl( giVT_OutputDevHandle, VIDEO_IOCTL_FINDMODE, &mode );
tmp = mode.id;
- giVT_RealWidth = mode.width;
- giVT_RealHeight = mode.height;
+ if( Width != mode.width || Height != mode.height )
+ {
+ Log_Warning("VTerm",
+ "Selected resolution (%ix%i is not supported) by the device, using (%ix%i)",
+ giVT_RealWidth, giVT_RealHeight,
+ mode.width, 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 );
+ // Resize text terminals if needed
+ if( giVT_RealWidth != mode.width || giVT_RealHeight != mode.height )
+ {
+ int newBufSize = (giVT_RealWidth/giVT_CharWidth)
+ *(giVT_RealHeight/giVT_CharHeight)
+ *(giVT_Scrollback+1);
+ //tVT_Char *tmp;
+ // Resize the text terminals
+ giVT_RealWidth = mode.width;
+ giVT_RealHeight = mode.height;
+ for( i = 0; i < NUM_VTS; i ++ )
+ {
+ if( gVT_Terminals[i].Mode != TERM_MODE_TEXT ) continue;
+
+ gVT_Terminals[i].Text = realloc(
+ gVT_Terminals[i].Text,
+ newBufSize*sizeof(tVT_Char)
+ );
+ }
+ }
+}
+
+void VT_SetMode(int Mode)
+{
+ VFS_IOCtl( giVT_OutputDevHandle, VIDEO_IOCTL_SETBUFFORMAT, &Mode );
}
/**
// Update current terminal ID
Log_Log("VTerm", "Changed terminal from %i to %i", giVT_CurrentTerminal, ID);
giVT_CurrentTerminal = ID;
+ gpVT_CurTerm = &gVT_Terminals[ID];
+
+ // Update cursor
+ if( gpVT_CurTerm->Mode == TERM_MODE_TEXT && !(gpVT_CurTerm->Flags & VT_FLAG_HIDECSR) )
+ {
+ tVideo_IOCtl_Pos pos;
+ pos.x = gpVT_CurTerm->WritePos % gpVT_CurTerm->Width;
+ pos.y = gpVT_CurTerm->WritePos / gpVT_CurTerm->Width;
+ VFS_IOCtl(giVT_OutputDevHandle, VIDEO_IOCTL_SETCURSOR, &pos);
+ }
+
+ if( gpVT_CurTerm->Mode == TERM_MODE_TEXT )
+ VT_SetMode( VIDEO_BUFFMT_TEXT );
+ else
+ VT_SetMode( VIDEO_BUFFMT_FRAMEBUFFER );
// Update the screen
VT_int_UpdateScreen( &gVT_Terminals[ ID ], 1 );
case KEY_F11: VT_SetTerminal(10); return;
case KEY_F12: VT_SetTerminal(11); return;
case KEY_PGUP:
+ if( gpVT_CurTerm->ViewPos > gpVT_CurTerm->Width )
+ gpVT_CurTerm->ViewPos -= gpVT_CurTerm->Width;
+ else
+ gpVT_CurTerm->ViewPos = 0;
return;
case KEY_PGDOWN:
+ if( gpVT_CurTerm->ViewPos < gpVT_CurTerm->Width*gpVT_CurTerm->Height*(giVT_Scrollback-1) )
+ gpVT_CurTerm->ViewPos += gpVT_CurTerm->Width;
+ else
+ gpVT_CurTerm->ViewPos = gpVT_CurTerm->Width*gpVT_CurTerm->Height*(giVT_Scrollback-1);
return;
}
}
}
}
-/**
- * \fn void VT_int_PutString(tVTerm *Term, Uint8 *Buffer, Uint Count)
- * \brief Print a string to the Virtual Terminal
- */
-void VT_int_PutString(tVTerm *Term, Uint8 *Buffer, Uint Count)
-{
- Uint32 val;
- int i;
- for( i = 0; i < Count; i++ )
- {
- if( Buffer[i] == 0x1B ) // Escape Sequence
- {
- i ++;
- i += VT_int_ParseEscape(Term, (char*)&Buffer[i]);
- continue;
- }
-
- if( Buffer[i] < 128 ) // Plain ASCII
- VT_int_PutChar(Term, Buffer[i]);
- else { // UTF-8
- i += ReadUTF8(&Buffer[i], &val);
- VT_int_PutChar(Term, val);
- }
- }
-
- // Update cursor
- if( !(Term->Flags & VT_FLAG_HIDECSR) )
- {
- tVideo_IOCtl_Pos pos;
- pos.x = Term->WritePos % Term->Width;
- pos.y = Term->WritePos / Term->Width;
- VFS_IOCtl(giVT_OutputDevHandle, VIDEO_IOCTL_SETCURSOR, &pos);
- }
-}
-
/**
* \fn void VT_int_ClearLine(tVTerm *Term, int Num)
* \brief Clears a line in a virtual terminal
char c;
int argc = 0, j = 1;
int tmp;
- int args[4] = {0,0,0,0};
+ int args[6] = {0,0,0,0};
- switch(Buffer[0]) {
+ switch(Buffer[0])
+ {
//Large Code
case '[':
// Get Arguments
- c = Buffer[1];
- do {
- while('0' <= c && c <= '9') {
- args[argc] *= 10;
- args[argc] += c-'0';
- c = Buffer[++j];
- }
- if( j != 1 ) argc ++;
- } while(c == ';');
+ c = Buffer[j++];
+ if( '0' <= c && c <= '9' )
+ {
+ do {
+ while('0' <= c && c <= '9') {
+ args[argc] *= 10;
+ args[argc] += c-'0';
+ c = Buffer[j++];
+ }
+ argc ++;
+ } while(c == ';');
+ }
+ /*
// Get string (what does this do?)
if(c == '"') {
- c = Buffer[++j];
+ c = Buffer[j++];
while(c != '"')
- c = Buffer[++j];
+ c = Buffer[j++];
}
+ */
+
+ //Log_Debug("VTerm", "argc = %i", argc);
// Get Command
if( ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'))
{
case 2:
{
- int i = Term->Height * VT_SCROLLBACK;
+ int i = Term->Height * (giVT_Scrollback + 1);
while( i-- ) VT_int_ClearLine(Term, i);
Term->WritePos = 0;
Term->ViewPos = 0;
}
}
break;
+ default:
+ Log_Warning("VTerm", "Unknown control sequence");
+ break;
}
}
break;
- default:
- break;
+ default: break;
+ }
+
+ //Log_Debug("VTerm", "j = %i, Buffer = '%s'", j, Buffer);
+ return j;
+}
+
+/**
+ * \fn void VT_int_PutString(tVTerm *Term, Uint8 *Buffer, Uint Count)
+ * \brief Print a string to the Virtual Terminal
+ */
+void VT_int_PutString(tVTerm *Term, Uint8 *Buffer, Uint Count)
+{
+ Uint32 val;
+ int i;
+ for( i = 0; i < Count; i++ )
+ {
+ if( Buffer[i] == 0x1B ) // Escape Sequence
+ {
+ i ++;
+ i += VT_int_ParseEscape(Term, (char*)&Buffer[i]) - 1;
+ continue;
+ }
+
+ if( Buffer[i] < 128 ) // Plain ASCII
+ VT_int_PutChar(Term, Buffer[i]);
+ else { // UTF-8
+ i += ReadUTF8(&Buffer[i], &val);
+ VT_int_PutChar(Term, val);
+ }
}
+ // Update Screen
+ VT_int_UpdateScreen( Term, 0 );
- return j + 1;
+ // Update cursor
+ if( Term == gpVT_CurTerm && !(Term->Flags & VT_FLAG_HIDECSR) )
+ {
+ tVideo_IOCtl_Pos pos;
+ pos.x = Term->WritePos % Term->Width;
+ pos.y = Term->WritePos / Term->Width;
+ VFS_IOCtl(giVT_OutputDevHandle, VIDEO_IOCTL_SETCURSOR, &pos);
+ }
}
/**
{
case '\0': return; // Ignore NULL byte
case '\n':
+ VT_int_UpdateScreen( Term, 0 ); // Update the line before newlining
Term->WritePos += Term->Width;
case '\r':
Term->WritePos -= Term->WritePos % Term->Width;
Term->WritePos ++;
break;
}
-
// Move Screen
- if(Term->WritePos >= Term->Width*Term->Height*VT_SCROLLBACK)
+ if(Term->WritePos >= Term->Width*Term->Height*(giVT_Scrollback+1))
{
int base, i;
Term->WritePos -= Term->Width;
+ VT_int_UpdateScreen( Term, 0 );
// Update view position
- base = Term->Width*Term->Height*(VT_SCROLLBACK-1);
+ base = Term->Width*Term->Height*(giVT_Scrollback-1);
if(Term->ViewPos < base) Term->ViewPos += Term->Width;
if(Term->ViewPos > base) Term->ViewPos = base;
// Scroll terminal cache
- base = Term->Width*(Term->Height*VT_SCROLLBACK-1);
+ base = Term->Width*(Term->Height*(giVT_Scrollback+1)-1);
// Scroll Back
memcpy(
Term->Text,
&Term->Text[Term->Width],
- Term->Width*(Term->Height-1)*VT_SCROLLBACK*sizeof(tVT_Char)
+ (Term->Width*Term->Height*(giVT_Scrollback+1)-Term->Width)*sizeof(tVT_Char)
);
// Clear last row
Term->Text[ base + i ].Colour = Term->CurColour;
}
- VT_int_UpdateScreen( Term, 1 );
+ //LOG("Scrolled buffer");
+ VT_int_ScrollFramebuffer( Term );
+ VT_int_UpdateScreen( Term, 0 );
}
- else if(Term->WritePos > Term->Width*Term->Height+Term->ViewPos)
+ else if(Term->WritePos >= Term->ViewPos + Term->Width*Term->Height)
{
+ //LOG("Scrolled screen");
+ Term->WritePos -= Term->Width;
+ VT_int_UpdateScreen( Term, 0 );
+ Term->WritePos += Term->Width;
+
Term->ViewPos += Term->Width;
- VT_int_UpdateScreen( Term, 1 );
- }
- else
+ VT_int_ScrollFramebuffer( Term );
VT_int_UpdateScreen( Term, 0 );
+ }
//LEAVE('-');
}
+/**
+ * \fn void VT_int_ScrollFramebuffer( tVTerm *Term )
+ * \note Scrolls the framebuffer by 1 text line
+ */
+void VT_int_ScrollFramebuffer( tVTerm *Term )
+{
+ int tmp;
+ struct {
+ Uint8 Op;
+ Uint16 DstX, DstY;
+ Uint16 SrcX, SrcY;
+ Uint16 W, H;
+ } PACKED buf;
+ // Only update if this is the current terminal
+ if( Term != gpVT_CurTerm ) return;
+
+ // This should only be called in text mode
+
+ tmp = VIDEO_BUFFMT_2DSTREAM;
+ VFS_IOCtl(giVT_OutputDevHandle, VIDEO_IOCTL_SETBUFFORMAT, &tmp);
+
+ buf.Op = VIDEO_2DOP_BLIT;
+ buf.DstX = 0; buf.DstY = 0;
+ buf.SrcX = 0; buf.SrcY = giVT_CharHeight;
+ buf.W = Term->Width * giVT_CharWidth;
+ buf.H = (Term->Height-1) * giVT_CharHeight;
+
+ VFS_WriteAt(giVT_OutputDevHandle, 0, 1+12, &buf);
+
+ // Restore old mode
+ tmp = VIDEO_BUFFMT_TEXT;
+ VFS_IOCtl(giVT_OutputDevHandle, VIDEO_IOCTL_SETBUFFORMAT, &tmp);
+}
+
/**
* \fn void VT_int_UpdateScreen( tVTerm *Term, int UpdateAll )
* \brief Updates the video framebuffer
void VT_int_UpdateScreen( tVTerm *Term, int UpdateAll )
{
// Only update if this is the current terminal
- if( Term != &gVT_Terminals[giVT_CurrentTerminal] ) return;
+ if( Term != gpVT_CurTerm ) return;
- if( Term->Mode == TERM_MODE_TEXT )
+ switch( Term->Mode )
{
- 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
+ case TERM_MODE_TEXT:
+ if(UpdateAll) {
+ //LOG("UpdateAll = 1");
+ //LOG("VFS_WriteAt(0x%x, 0, %i*sizeof(tVT_Char), &Term->Text[%i])",
+ // giVT_OutputDevHandle, Term->Width*Term->Height, Term->ViewPos);
+ 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;
+ //LOG("UpdateAll = 0");
+ //LOG("VFS_WriteAt(0x%x, %i*sizeof(tVT_Char), %i*sizeof(tVT_Char), &Term->Text[%i])",
+ // giVT_OutputDevHandle, (pos - Term->ViewPos), Term->Width, pos);
+ VFS_WriteAt(
+ giVT_OutputDevHandle,
+ (pos - Term->ViewPos)*sizeof(tVT_Char),
+ Term->Width*sizeof(tVT_Char),
+ &Term->Text[pos]
+ );
}
- }
- else
- {
+ break;
+ case TERM_MODE_FB:
VFS_WriteAt(
giVT_OutputDevHandle,
0,
Term->Width*Term->Height*sizeof(Uint32),
- &Term->Buffer
+ Term->Buffer
);
+ break;
}
}
switch(NewMode)
{
case TERM_MODE_TEXT:
+ Log_Log("VTerm", "Set VT %p to text mode", Term);
free(Term->Buffer);
- Term->Text = calloc( Term->Width*Term->Height*VT_SCROLLBACK, sizeof(tVT_Char) );
+ Term->Text = calloc( Term->Width*Term->Height*(giVT_Scrollback+1), sizeof(tVT_Char) );
break;
case TERM_MODE_FB:
+ Log_Log("VTerm", "Set VT %p to framebuffer mode (%ix%i)", Term,
+ Term->Width, Term->Height);
free(Term->Text);
Term->Buffer = calloc( Term->Width*Term->Height, sizeof(Uint32) );
+ Log_Debug("VTerm", "Term->Buffer = %p", Term->Buffer);
break;
- //case TERM_MODE_OPENGL:
+ //case TERM_MODE_2DACCEL:
+ //case TERM_MODE_3DACCEL:
// return;
}
Uint8 *VT_Font_GetChar(Uint32 Codepoint);
// === GLOBALS ===
-int giVT_CharWidth = FONT_WIDTH+1;
+int giVT_CharWidth = FONT_WIDTH;
int giVT_CharHeight = FONT_HEIGHT;
// === CODE ===
#define DEBUG 0
#include <acess.h>
#include <tpl_drv_disk.h>
+#include <tpl_drv_video.h>
// === CODE ===
+// --- Video Driver Helpers ---
+Uint64 DrvUtil_Video_2DStream(void *Ent, void *Buffer, int Length,
+ tDrvUtil_Video_2DHandlers *Handlers, int SizeofHandlers)
+{
+ Uint8 *stream = Buffer;
+ int rem = Length;
+ int op;
+ while( rem )
+ {
+ rem --;
+ op = *stream++;
+
+ if(op > NUM_VIDEO_2DOPS) {
+ Log_Warning("DrvUtil", "DrvUtil_Video_2DStream: Unknown"
+ " operation %i", op);
+ }
+
+ if(op*4 > SizeofHandlers) {
+ Log_Warning("DrvUtil", "DrvUtil_Video_2DStream: Driver does"
+ " not support op %i", op);
+ return Length-rem;
+ }
+
+ switch(op)
+ {
+ case VIDEO_2DOP_NOP: break;
+
+ case VIDEO_2DOP_FILL:
+ if(rem < 12) return Length-rem;
+
+ if(!Handlers->Fill) {
+ Log_Warning("DrvUtil", "DrvUtil_Video_2DStream: Driver"
+ " does not support VIDEO_2DOP_FILL");
+ return Length-rem;
+ }
+
+ Handlers->Fill(
+ Ent,
+ *(Uint16*)(&stream[0]), *(Uint16*)(&stream[2]),
+ *(Uint16*)(&stream[4]), *(Uint16*)(&stream[6]),
+ *(Uint32*)(&stream[8])
+ );
+
+ rem -= 12;
+ stream += 12;
+ break;
+
+ case VIDEO_2DOP_BLIT:
+ if(rem < 12) return Length-rem;
+
+ if(!Handlers->Blit) {
+ Log_Warning("DrvUtil", "DrvUtil_Video_2DStream: Driver"
+ " does not support VIDEO_2DOP_BLIT");
+ return Length-rem;
+ }
+
+ Handlers->Blit(
+ Ent,
+ *(Uint16*)(&stream[0]), *(Uint16*)(&stream[2]),
+ *(Uint16*)(&stream[4]), *(Uint16*)(&stream[6]),
+ *(Uint16*)(&stream[8]), *(Uint16*)(&stream[10])
+ );
+
+ rem -= 12;
+ stream += 12;
+ break;
+
+ }
+ }
+ return 0;
+}
+
+// --- Disk Driver Helpers ---
Uint64 DrvUtil_ReadBlock(Uint64 Start, Uint64 Length, void *Buffer,
tDrvUtil_Callback ReadBlocks, Uint64 BlockSize, Uint Argument)
{
*/
// === FUNCTIONS ===
-// --- Core ---
-extern void System_Init(char *ArgString);
-
// --- IRQs ---
extern int IRQ_AddHandler(int Num, void (*Callback)(int));
* \name Debugging and Errors
* \{
*/
-extern void Panic(char *Msg, ...);
-extern void Warning(char *Msg, ...);
-extern void Log(char *Fmt, ...);
-extern void LogV(char *Fmt, va_list Args);
-extern void LogF(char *Fmt, ...);
+extern void Debug_KernelPanic(); //!< Initiate a kernel panic
+extern void Panic(char *Msg, ...); //!< Print a panic message (initiates a kernel panic)
+extern void Warning(char *Msg, ...); //!< Print a warning message
+extern void LogF(char *Fmt, ...); //!< Print a log message without a trailing newline
+extern void Log(char *Fmt, ...); //!< Print a log message
+extern void LogV(char *Fmt, va_list Args); //!< va_list Log message
extern void Debug_Enter(char *FuncName, char *ArgTypes, ...);
extern void Debug_Log(char *FuncName, char *Fmt, ...);
extern void Debug_Leave(char *FuncName, char RetType, ...);
extern int strncmp(const char *Str1, const char *Str2, size_t num);
extern int strucmp(const char *Str1, const char *Str2);
extern char *strdup(const char *Str);
+extern char **str_split(const char *__str, char __ch);
extern int strpos(const char *Str, char Ch);
extern int strpos8(const char *str, Uint32 search);
extern void itoa(char *buf, Uint num, int base, int minLength, char pad);
#include <binary_ext.h>
#include <vfs_ext.h>
+#include <adt.h>
#endif
--- /dev/null
+/*
+ * Acess2
+ * - Abstract Data Types
+ */
+#ifndef _ADT_H_
+#define _ADT_H_
+
+/**
+ * \name Ring Buffers
+ * \{
+ */
+typedef struct sRingBuffer
+{
+ size_t Start; //!< Start of data in ring buffer
+ size_t Length; //!< Number of data bytes in buffer
+ size_t Space; //!< Allocated space in buffer
+ char Data[]; //!< Buffer
+} tRingBuffer;
+
+/**
+ * \brief Create a ring buffer \a Space bytes large
+ * \param Space Ammount of space to allocate within the buffer
+ * \return Pointer to the buffer structure
+ */
+extern tRingBuffer *RingBuffer_Create(size_t Space);
+/**
+ * \brief Read at most \a Length bytes from the buffer
+ * \param Dest Destinaton buffer
+ * \param Buffer Source ring buffer
+ * \param Length Requested number of bytes
+ * \return Number of bytes read
+ */
+extern size_t RingBuffer_Read(void *Dest, tRingBuffer *Buffer, size_t Length);
+/**
+ * \brief Write at most \a Length bytes to the buffer
+ * \param Buffer Destination ring buffer
+ * \param Source Source buffer
+ * \param Length Provided number of bytes
+ * \return Number of bytes written
+ */
+extern size_t RingBuffer_Write(tRingBuffer *Buffer, void *Source, size_t Length);
+/**
+ * \}
+ */
+
+
+#endif
* 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
+ * \ref fs_sysfs.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
* framebuffer (this may not be the true framebuffer, to allow for double-buffering)
* to the user. See the full documentation in tpl_drv_video.h for the
* complete specifcation.
+ *
+ * \subsection drv_disk Disk/Storage Devices
+ * Storage devices present themselves as a linear collection of bytes.
+ * Reads and writes to the device need not be aligned to the stated block
+ * size, but it is suggested that users of a storage device file align
+ * their accesses to block boundaries.
+ * The functions DrvUtil_ReadBlock and DrvUtil_WriteBlock are provided
+ * to storage drivers to assist in handling non-alinged reads and writes.
+ *
+ * \see tpl_drv_common.h Common Spec.
+ * \see tpl_drv_video.h Video Device Spec.
+ * \see tpl_drv_keyboard.h Keyboard Device Spec.
+ * \see tpl_drv_disk.h Disk/Storage Device Spec.
+ * \see tpl_drv_network.h Network Device Spec.
+ * \see tpl_drv_terminal.h Virtual Terminal Spec.
*/
EACCES,
ENOTFOUND,
EREADONLY,
- ENOTIMPL
+ ENOTIMPL,
+ ENOENT,
+ ENFILE,
+ ENOTDIR,
+
+ NUM_ERRS
};
#endif
// === FUNCTIONS ===
/**
- * \fn int DevFS_AddDevice(tDevFS_Driver *Dev)
+ * \fn int DevFS_AddDevice(tDevFS_Driver *Device)
* \brief Registers a device in the Device Filesystem
* \param Device Pointer to a persistant structure that represents the driver
* \return Boolean success
SYS_EXIT, // 0 - Kill this thread
SYS_CLONE, // 1 - Create a new thread
SYS_KILL, // 2 - Send a signal
- SYS_SIGNAL, // 3 - Set signal Handler
+ SYS_SETFAULTHANDLER, // 3 - Set signal Handler
SYS_YIELD, // 4 - Yield remainder of timestamp
SYS_SLEEP, // 5 - Sleep until messaged or signaled
SYS_WAIT, // 6 - Wait for a time or a message
SYS_WRITE, // 68 - Write to an open file
SYS_IOCTL, // 69 - Perform an IOCtl Call
SYS_READDIR, // 70 - Read from an open directory
- SYS_MKDIR, // 71 - Create a new directory
- SYS_SYMLINK, // 72 - Create a symbolic link
- SYS_GETACL, // 73 - Get an ACL Value
- SYS_SETACL, // 74 - Set an ACL Value
- SYS_FINFO, // 75 - Get file information
- SYS_SEEK, // 76 - Seek to a new position in the file
- SYS_TELL, // 77 - Return the current file position
- SYS_CHDIR, // 78 - Change current directory
- SYS_GETCWD, // 79 - Get current directory
- SYS_MOUNT, // 80 - Mount a filesystem
+ SYS_OPENCHILD, // 71 - Open a child entry in a directory
+ SYS_MKDIR, // 72 - Create a new directory
+ SYS_SYMLINK, // 73 - Create a symbolic link
+ SYS_GETACL, // 74 - Get an ACL Value
+ SYS_SETACL, // 75 - Set an ACL Value
+ SYS_FINFO, // 76 - Get file information
+ SYS_SEEK, // 77 - Seek to a new position in the file
+ SYS_TELL, // 78 - Return the current file position
+ SYS_CHDIR, // 79 - Change current directory
+ SYS_GETCWD, // 80 - Get current directory
+ SYS_MOUNT, // 81 - Mount a filesystem
NUM_SYSCALLS,
SYS_DEBUG = 0x100 // 0x100 - Print a debug string
};
static const char *cSYSCALL_NAMES[] = {
- "SYS_EXIT","SYS_CLONE","SYS_KILL","SYS_SIGNAL","SYS_YIELD","SYS_SLEEP",
+ "SYS_EXIT","SYS_CLONE","SYS_KILL","SYS_SETFAULTHANDLER","SYS_YIELD","SYS_SLEEP",
"SYS_WAIT","SYS_WAITTID","SYS_SETNAME","SYS_GETNAME","SYS_GETTID","SYS_GETPID",
"SYS_SETPRI","SYS_SENDMSG","SYS_GETMSG","SYS_GETTIME","SYS_SPAWN","SYS_EXECVE",
"SYS_LOADBIN","SYS_UNLOADBIN","SYS_LOADMOD","","","",
"","","","","","",
"","","","","","",
"","","","","SYS_OPEN","SYS_REOPEN",
- "SYS_CLOSE","SYS_READ","SYS_WRITE","SYS_IOCTL","SYS_READDIR","SYS_MKDIR",
- "SYS_SYMLINK","SYS_GETACL","SYS_SETACL","SYS_FINFO","SYS_SEEK","SYS_TELL",
- "SYS_CHDIR","SYS_GETCWD","SYS_MOUNT",""
+ "SYS_CLOSE","SYS_READ","SYS_WRITE","SYS_IOCTL","SYS_READDIR","SYS_OPENCHILD",
+ "SYS_MKDIR","SYS_SYMLINK","SYS_GETACL","SYS_SETACL","SYS_FINFO","SYS_SEEK",
+ "SYS_TELL","SYS_CHDIR","SYS_GETCWD","SYS_MOUNT",""
};
#endif
%define SYS_EXIT 0 ; Kill this thread
%define SYS_CLONE 1 ; Create a new thread
%define SYS_KILL 2 ; Send a signal
-%define SYS_SIGNAL 3 ; Set signal Handler
+%define SYS_SETFAULTHANDLER 3 ; Set signal Handler
%define SYS_YIELD 4 ; Yield remainder of timestamp
%define SYS_SLEEP 5 ; Sleep until messaged or signaled
%define SYS_WAIT 6 ; Wait for a time or a message
%define SYS_WRITE 68 ; Write to an open file
%define SYS_IOCTL 69 ; Perform an IOCtl Call
%define SYS_READDIR 70 ; Read from an open directory
-%define SYS_MKDIR 71 ; Create a new directory
-%define SYS_SYMLINK 72 ; Create a symbolic link
-%define SYS_GETACL 73 ; Get an ACL Value
-%define SYS_SETACL 74 ; Set an ACL Value
-%define SYS_FINFO 75 ; Get file information
-%define SYS_SEEK 76 ; Seek to a new position in the file
-%define SYS_TELL 77 ; Return the current file position
-%define SYS_CHDIR 78 ; Change current directory
-%define SYS_GETCWD 79 ; Get current directory
-%define SYS_MOUNT 80 ; Mount a filesystem
+%define SYS_OPENCHILD 71 ; Open a child entry in a directory
+%define SYS_MKDIR 72 ; Create a new directory
+%define SYS_SYMLINK 73 ; Create a symbolic link
+%define SYS_GETACL 74 ; Get an ACL Value
+%define SYS_SETACL 75 ; Set an ACL Value
+%define SYS_FINFO 76 ; Get file information
+%define SYS_SEEK 77 ; Seek to a new position in the file
+%define SYS_TELL 78 ; Return the current file position
+%define SYS_CHDIR 79 ; Change current directory
+%define SYS_GETCWD 80 ; Get current directory
+%define SYS_MOUNT 81 ; Mount a filesystem
typedef struct sThread
{
// --- threads.c's
+ // 0
struct sThread *Next; //!< Next thread in list
tSpinlock IsLocked; //!< Thread's spinlock
volatile int Status; //!< Thread Status
int RetStatus; //!< Return Status
+ // 16
Uint TID; //!< Thread ID
Uint TGID; //!< Thread Group (Process)
Uint PTID; //!< Parent Thread ID
char *ThreadName; //!< Name of thread
// --- arch/proc.c's responsibility
+ // 40
//! Kernel Stack Base
tVAddr KernelStack;
+ // 44 (x86)
//! Memory Manager State
tMemoryState MemState;
+ // 48 (x86)
//! State on task switch
tTaskState SavedState;
// --- threads.c's
- int CurSignal; //!< Signal currently being handled (0 for none)
- tVAddr SignalHandlers[NSIG]; //!< Signal Handler List
- tTaskState SignalState; //!< Saved state for signal handler
+ // 60
+ int CurFaultNum; //!< Current fault number, 0: none
+ tVAddr FaultHandler; //!< Fault Handler
tMsg * volatile Messages; //!< Message Queue
tMsg *LastMessage; //!< Last Message (speeds up insertion)
THREAD_STAT_DEAD
};
+enum eFaultNumbers
+{
+ FAULT_MISC,
+ FAULT_PAGE,
+ FAULT_ACCESS,
+ FAULT_DIV0,
+ FAULT_OPCODE,
+ FAULT_FLOAT
+};
+
// === FUNCTIONS ===
extern tThread *Proc_GetCurThread();
extern tThread *Threads_GetThread(Uint TID);
* \brief Disk Driver Interface Definitions\r
* \author John Hodge (thePowersGang)\r
* \r
+ * \section Nomeclature\r
+ * All addreses are 64-bit counts of bytes from the logical beginning of\r
+ * the disk unless explicitly stated.\r
+ * \r
* \section dirs VFS Layout\r
* Disk drivers have a flexible directory layout. The root directory can\r
* contain subdirectories, with the only conditions being that all nodes\r
* \brief Get the block size\r
* \return Size of a hardware block for this device\r
*/\r
- DISK_IOCTL_GETBLOCKSIZE = 4\r
+ DISK_IOCTL_GETBLOCKSIZE = 4,\r
+ \r
+ /**\r
+ * ioctl(..., tTplDisk_CacheRegion *RegionInfo)\r
+ * \brief Sets the cache importantce and protocol for a section of\r
+ * memory.\r
+ * \param RegionInfo Pointer to a region information structure\r
+ * \return Boolean failure\r
+ */\r
+ DISK_IOCTL_SETCACHEREGION,\r
+ \r
+ /**\r
+ * ioctl(..., Uint64 *Info[2])\r
+ * \brief Asks the driver to precache a region of disk.\r
+ * \param Region 64-bit Address and Size pair describing the area to cache\r
+ * \return Number of blocks cached\r
+ */\r
+ DISK_IOCTL_PRECACHE,\r
+ \r
+ /**\r
+ * ioclt(..., Uint64 *Region[2])\r
+ * \brief Asks to driver to flush the region back to disk\r
+ * \param Region 64-bit Address and Size pair describing the area to flush\r
+ * \note If Region[0] == -1 then the entire disk's cache is flushed\r
+ * \return Number of blocks flushed (or 0 for entire disk)\r
+ */\r
+ DISK_IOCTL_FLUSH\r
+};\r
+\r
+/**\r
+ * \brief Describes the cache parameters of a region on the disk\r
+ */\r
+typedef struct sTplDisk_CacheRegion\r
+{\r
+ Uint64 Base; //!< Base of cache region\r
+ Uint64 Length; //!< Size of cache region\r
+ /**\r
+ * \brief Cache Protocol & Flags\r
+ * \r
+ * The low 4 bits denot the cache protocol to be used by the\r
+ * region (see ::eTplDisk_CacheProtocols for a list).\r
+ * The high 4 bits denote flags to apply to the cache (see\r
+ * ::eTplDisk_CacheFlags)\r
+ */\r
+ Uint8 Flags;\r
+ Uint8 Priority; //!< Lower is a higher proritory\r
+ /**\r
+ * \brief Maximum size of cache, in blocks\r
+ * \note If CacheSize is zero, the implemenation defined limit is used\r
+ */\r
+ Uint16 CacheSize;\r
+} tTplDisk_CacheRegion;\r
+\r
+/**\r
+ * \brief Cache protocols to use\r
+ */\r
+enum eTplDisk_CacheProtocols\r
+{\r
+ /**\r
+ * \brief Don't cache the region\r
+ */\r
+ \r
+ DISK_CACHEPROTO_DONTCACHE,\r
+ /**\r
+ * \brief Most recently used blocks cached\r
+ * \note This is the default action for undefined regions\r
+ */\r
+ DISK_CACHEPROTO_RECENTLYUSED,\r
+ /**\r
+ * \brief Cache the entire region in memory\r
+ * \r
+ * This is a faster version of setting Length to CacheSize*BlockSize\r
+ */\r
+ DISK_CACHEPROTO_FULLCACHE,\r
+ \r
+ /**\r
+ * \brief Cache only on demand\r
+ * \r
+ * Only cache when the ::DISK_IOCTL_PRECACHE IOCtl is used\r
+ */\r
+ DISK_CACHEPROTO_EXPLICIT\r
+};\r
+\r
+/**\r
+ * \brief Flags for the cache\r
+ */\r
+enum eTplDisk_CacheFlags\r
+{\r
+ /**\r
+ * \brief Write all changes to the region straight back to media\r
+ */\r
+ DISK_CACHEFLAG_WRITETHROUGH = 0x10\r
};\r
\r
/**\r
* \brief IOCtl name strings\r
*/\r
-#define DRV_DISK_IOCTLNAMES "get_block_size"\r
+#define DRV_DISK_IOCTLNAMES "get_block_size","set_cache_region","set_precache"\r
+\r
+/**\r
+ * \name Disk Driver Utilities\r
+ * \{\r
+ */\r
\r
/**\r
* \brief Callback function type used by DrvUtil_ReadBlock and DrvUtil_WriteBlock\r
tDrvUtil_Callback ReadBlocks, tDrvUtil_Callback WriteBlocks,\r
Uint64 BlockSize, Uint Argument);\r
\r
+/**\r
+ * \}\r
+ */\r
+\r
#endif\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
* Reading from the screen must either return zero, or read from the\r
* framebuffer.\r
* \r
*/\r
enum eTplVideo_BufFormats\r
{\r
+ /**\r
+ * \brief Text Mode\r
+ * \r
+ * The device file presents itself as an array of ::tVT_Char\r
+ * each describing a character cell on the screen.\r
+ * These cells are each \a giVT_CharWidth pixels wide and\r
+ * \a giVT_CharHeight high.\r
+ */\r
VIDEO_BUFFMT_TEXT,\r
+ /**\r
+ * \brief Framebuffer Mode\r
+ * \r
+ * The device file presents as an array of 32-bpp pixels describing\r
+ * the entire screen. The format of a single pixel is in xRGB format\r
+ * (top 8 bits ignored, next 8 bits red, next 8 bits green and\r
+ * the bottom 8 bits blue)\r
+ */\r
VIDEO_BUFFMT_FRAMEBUFFER,\r
+ /**\r
+ * \brief 2D Accelerated Mode\r
+ * \r
+ * The device file acts as a character device, accepting a stream of\r
+ * commands described in eTplVideo_2DCommands when written to.\r
+ */\r
+ VIDEO_BUFFMT_2DSTREAM,\r
+ /**\r
+ * \brief 3D Accelerated Mode\r
+ * \r
+ * The device file acts as a character device, accepting a stream of\r
+ * commands described in eTplVideo_3DCommands when written to.\r
+ */\r
VIDEO_BUFFMT_3DSTREAM\r
};\r
\r
+/**\r
+ * \brief 2D Accellerated Video Commands\r
+ * \r
+ * Commands passed in the command stream for ::VIDEO_BUFFMT_2DSTREAM\r
+ */\r
+enum eTplVideo_2DCommands\r
+{\r
+ /**\r
+ * \brief No Operation\r
+ */\r
+ VIDEO_2DOP_NOP,\r
+ /**\r
+ * \brief Fill a region\r
+ * \param X Uint16 - Leftmost pixels of the region\r
+ * \param Y Uint16 - Topmost pixels of the region\r
+ * \param W Uint16 - Width of the region\r
+ * \param H Uint16 - Height of the region\r
+ * \param Colour Uint32 - Value to fill with\r
+ */\r
+ VIDEO_2DOP_FILL,\r
+ /**\r
+ * \brief Copy a region from one part of the framebuffer to another\r
+ * \param DestX Uint16 - Leftmost pixels of the destination\r
+ * \param DestY Uint16 - Topmost pixels of the destination\r
+ * \param SrcX Uint16 - Leftmost pixels of the source\r
+ * \param SrcY Uint16 - Topmost pixels of the source\r
+ * \param Width Uint16 - Width of the region\r
+ * \param Height Uint16 - Height of the region\r
+ */\r
+ VIDEO_2DOP_BLIT,\r
+\r
+\r
+ /**\r
+ * \brief Copy a region from video memory to the framebuffer\r
+ */\r
+ VIDEO_2DOP_BLITBUF,\r
+\r
+ /**\r
+ * \brief Copy and scale a region from video memory to the framebuffer\r
+ */\r
+ VIDEO_2DOP_BLITSCALEBUF,\r
+\r
+ NUM_VIDEO_2DOPS\r
+};\r
+\r
/**\r
* \brief Describes a position in the video framebuffer\r
*/\r
*/\r
extern Uint32 VT_Colour12to24(Uint16 Col12);\r
\r
+/**\r
+ * \brief Handlers for eTplVideo_2DCommands\r
+ */\r
+typedef struct sDrvUtil_Video_2DHandlers\r
+{\r
+ /**\r
+ * \brief No Operation, Ignored\r
+ * \see VIDEO_2DOP_NOP\r
+ */\r
+ void *Nop;\r
+ /**\r
+ * \brief Fill a buffer region\r
+ * \param X Lefthand edge\r
+ * \param Y Top edge\r
+ * \param W Width\r
+ * \param H Height\r
+ * \param Colour Colour to fill with\r
+ * \see VIDEO_2DOP_FILL\r
+ */\r
+ void (*Fill)(void *Ent, Uint16 X, Uint16 Y, Uint16 W, Uint16 H, Uint32 Colour);\r
+ /**\r
+ * \brief Fill a buffer region\r
+ * \param DestX Lefthand edge of destination\r
+ * \param DestY Top edge of destination\r
+ * \param SrcX Lefthand edge of source\r
+ * \param SrcY Top edge of source\r
+ * \param W Width\r
+ * \param H Height\r
+ * \see VIDEO_2DOP_BLIT\r
+ */\r
+ void (*Blit)(void *Ent, Uint16 DestX, Uint16 DestY, Uint16 SrcX, Uint16 SrcY, Uint16 W, Uint16 H);\r
+} tDrvUtil_Video_2DHandlers;\r
+\r
+/**\r
+ * \brief Handle a 2D operation stream for a driver\r
+ * \param Ent Value to pass to handlers\r
+ * \param Buffer Stream buffer\r
+ * \param Length Length of stream\r
+ * \param Handlers Handlers to use for the stream\r
+ * \param SizeofHandlers Size of \a tDrvUtil_Video_2DHandlers according\r
+ * to the driver. Used as version control and error avoidence.\r
+ */\r
+extern Uint64 DrvUtil_Video_2DStream(void *Ent, void *Buffer, int Length,\r
+ tDrvUtil_Video_2DHandlers *Handlers, int SizeofHandlers);\r
+\r
#endif\r
* \return Boolean Success
*/
extern int VFS_ReadDir(int FD, char *Dest);
+/**
+ * \brief Opens a file via an open directory
+ * \note The file to open must be a direct child of the parent
+ * \param Errno Error number
+ * \param FD Parent Directory
+ * \param Name Child name
+ * \param Mode Open mode
+ * \return File handle (same as returned from VFS_Open)
+ */
+extern int VFS_OpenChild(Uint *Errno, int FD, char *Name, Uint Mode);
#endif
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);
+char **str_split(const char *__str, char __ch);
int strpos8(const char *str, Uint32 Search);
int ReadUTF8(Uint8 *str, Uint32 *Val);
int WriteUTF8(Uint8 *str, Uint32 Val);
+ int DivUp(int num, int dem);
Sint64 timestamp(int sec, int mins, int hrs, int day, int month, int year);
Uint rand(void);
int CheckString(char *String);
EXPORT(strcmp);
EXPORT(strncmp);
EXPORT(strdup);
-EXPORT(DivUp);
+EXPORT(str_split);
EXPORT(strpos8);
+EXPORT(DivUp);
EXPORT(ReadUTF8);
EXPORT(WriteUTF8);
EXPORT(timestamp);
int vsnprintf(char *__s, size_t __maxlen, 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 val;
size_t pos = 0;
// Flags
- // int bPadLeft = 0;
+ int bPadLeft = 0;
//Log("vsnprintf: (__s=%p, __maxlen=%i, __format='%s', ...)", __s, __maxlen, __format);
// Get Argument
val = va_arg(args, Uint);
- //Log("val = %x", val);
+
+ // - Padding Side Flag
+ if(c == '+') {
+ bPadLeft = 1;
+ c = *__format++;
+ }
// - Padding
if(c == '0') {
pad = ' ';
// - Minimum length
- minSize = 1;
- if('1' <= c && c <= '9')
+ if(c == '*') {
+ minSize = val;
+ val = va_arg(args, Uint);
+ c = *__format++;
+ }
+ else if('1' <= c && c <= '9')
{
minSize = 0;
while('0' <= c && c <= '9')
c = *__format++;
}
}
+ else
+ minSize = 1;
// - Default, Long or LongLong?
isLongLong = 0;
case 's':
p = (char*)(Uint)val;
printString:
- //Log("p = '%s'", p);
if(!p) p = "(null)";
+ len = strlen(p);
+ if( !bPadLeft ) while(len++ < minSize) PUTCH(pad);
while(*p) PUTCH(*p++);
+ if( bPadLeft ) while(len++ < minSize) PUTCH(pad);
break;
case 'C': // Non-Null Terminated Character Array
p = (char*)(Uint)val;
if(!p) goto printString;
+ //while(minSize--) PUTCH(*p++);
while(minSize--) PUTCH(*p++);
break;
return ret;
}
+/**
+ * \brief Split a string using the passed character
+ * \return NULL terminated array of strings on the heap
+ * \param __str String to split
+ * \param __ch Character to split by
+ */
+char **str_split(const char *__str, char __ch)
+{
+ int i, j;
+ int len = 1;
+ char **ret;
+ char *start;
+
+ for( i = 0; __str[i]; i++ )
+ {
+ if(__str[i] == __ch)
+ len ++;
+ }
+
+ ret = malloc( sizeof(char*)*(len+1) + (i + 1) );
+ if( !ret ) return NULL;
+
+ j = 1;
+ start = (char *)&ret[len+1];
+ ret[0] = start;
+ for( i = 0; __str[i]; i++ )
+ {
+ if(__str[i] == __ch) {
+ *start++ = '\0';
+ ret[j++] = start;
+ }
+ else {
+ *start++ = __str[i];
+ }
+ }
+ *start = '\0';
+ ret[j] = NULL;
+
+ return ret;
+}
+
/**
* \fn int DivUp(int num, int dem)
* \brief Divide two numbers, rounding up
LOG_LEVEL_DEBUG,
NUM_LOG_LEVELS
};
-const char *csaLevelCodes[] = {"k","p","f","e","w","n","l","d"};
+const char *csaLevelColours[] = {
+ "\x1B[35m", "\x1B[34m", "\x1B[36m", "\x1B[31m",
+ "\x1B[33m", "\x1B[32m", "\x1B[0m", "\x1B[0m"
+ };
+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 Ident[9];
char Data[];
} tLogEntry;
typedef struct sLogList
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);
ent = malloc(sizeof(tLogEntry)+len+1);
ent->Time = now();
- strncpy(ent->Ident, Ident, 7);
+ strncpy(ent->Ident, Ident, 8);
ent->Level = Level;
ent->Length = len;
vsnprintf( ent->Data, 256, Format, Args );
*/
void Log_Int_PrintMessage(tLogEntry *Entry)
{
- LogF("%018lli%s [%+8s] %s\n",
+ LogF("%s%018lli%s [%+8s] %s\x1B[0m\n",
+ csaLevelColours[Entry->Level],
Entry->Time,
csaLevelCodes[Entry->Level],
Entry->Ident,
#define USE_UDI 0
// === PROTOTYPES ===
- int Modules_LoadBuiltins(void);
+ int Module_int_Initialise(tModule *Module, char *ArgString);
+void Modules_LoadBuiltins(void);
+void Modules_SetBuiltinParams(char *Name, char *ArgString);
int Module_RegisterLoader(tModuleLoader *Loader);
int Module_LoadMem(void *Buffer, Uint Length, char *ArgString);
int Module_LoadFile(char *Path, char *ArgString);
tModule *gLoadedModules = NULL;
tModuleLoader *gModule_Loaders = NULL;
tModule *gLoadingModules = NULL;
+char **gasBuiltinModuleArgs;
// === CODE ===
/**
* \retval 0 Returned on success
* \retval >0 Error code form the module's initialisation function
*/
-int Module_int_Initialise(tModule *Module)
+int Module_int_Initialise(tModule *Module, char *ArgString)
{
int i, j;
int ret;
char **deps;
+ char **args;
tModule *mod;
ENTER("pModule", Module);
}
// Dependency is not loaded, so load it
- ret = Module_int_Initialise( &gKernelModules[i] );
+ ret = Module_int_Initialise(
+ &gKernelModules[i],
+ gasBuiltinModuleArgs ? gasBuiltinModuleArgs[i] : NULL
+ );
if( ret )
{
// The only "ok" error is NOTNEEDED
Module->Version >> 8, Module->Version & 0xFF
);
- ret = Module->Init(NULL);
+ if( ArgString )
+ args = str_split( ArgString, ',' );
+ else
+ args = NULL;
+
+ ret = Module->Init(args);
+
+ if(args) free(args);
+
if( ret != MODULE_ERR_OK ) {
switch(ret)
{
LEAVE_RET('i', ret);
return ret;
}
+ LOG("ret = %i", ret);
// Remove from loading list
gLoadingModules = gLoadingModules->Next;
/**
* \brief Initialises builtin modules
*/
-int Modules_LoadBuiltins()
+void Modules_LoadBuiltins()
{
int i;
for( i = 0; i < giNumBuiltinModules; i++ )
{
- Module_int_Initialise( &gKernelModules[i] );
+ Module_int_Initialise(
+ &gKernelModules[i],
+ (gasBuiltinModuleArgs ? gasBuiltinModuleArgs[i] : NULL)
+ );
}
- return 0;
+ if( gasBuiltinModuleArgs != NULL )
+ free(gasBuiltinModuleArgs);
+}
+
+/**
+ * \brief Sets the parameters for a builtin module
+ */
+void Modules_SetBuiltinParams(char *Name, char *ArgString)
+{
+ int i;
+ if( gasBuiltinModuleArgs == NULL ) {
+ giNumBuiltinModules = (Uint)&gKernelModulesEnd - (Uint)&gKernelModules;
+ giNumBuiltinModules /= sizeof(tModule);
+ gasBuiltinModuleArgs = calloc( giNumBuiltinModules, sizeof(char*) );
+ }
+
+ for( i = 0; i < giNumBuiltinModules; i ++ )
+ {
+ if(strcmp( gKernelModules[i].Name, Name ) == 0) {
+ gasBuiltinModuleArgs[i] = ArgString;
+ return ;
+ }
+ }
+
+ Log_Warning("Modules", "Unknown builtin kernel module '%s'", Name);
}
/**
}
#if 1
- if( Module_int_Initialise( info ) )
+ if( Module_int_Initialise( info, ArgString ) )
{
Binary_Unload(base);
return 0;
extern int Threads_SetUID(Uint *errno, tUID ID);
extern tGID Threads_GetGID();
extern int Threads_SetGID(Uint *errno, tGID ID);
+extern int Threads_SetFaultHandler(Uint Handler);
// === PROTOTYPES ===
int Syscall_ValidString(Uint Addr);
// -- Yield current timeslice
case SYS_YIELD: Threads_Yield(); break;
+ // -- Set Error Handler
+ case SYS_SETFAULTHANDLER:
+ Threads_SetFaultHandler(Regs->Arg1);
+ break;
+
// -- Clone the current thread
case SYS_CLONE:
// Call clone system call
break;
case SYS_SEEK:
+ #if BITS == 64
ret = VFS_Seek( Regs->Arg1, Regs->Arg2, Regs->Arg3 );
+ #else
+ ret = VFS_Seek( Regs->Arg1, Regs->Arg2|(((Uint64)Regs->Arg3)<<32), Regs->Arg4 );
+ #endif
break;
case SYS_TELL:
ret = VFS_ReadDir( Regs->Arg1, (void*)Regs->Arg2 );
break;
+ // Open a file that is a entry in an open directory
+ case SYS_OPENCHILD:
+ if( !Syscall_ValidString(Regs->Arg2) ) {
+ err = -EINVAL;
+ ret = -1;
+ break;
+ }
+ ret = VFS_OpenChild( &err, Regs->Arg1, (char*)Regs->Arg2, Regs->Arg3);
+ break;
+
// Change Directory
case SYS_CHDIR:
if( !Syscall_ValidString(Regs->Arg1) ) {
SYS_EXIT Kill this thread
SYS_CLONE Create a new thread
SYS_KILL Send a signal
-SYS_SIGNAL Set signal Handler
+SYS_SETFAULTHANDLER Set signal Handler
SYS_YIELD Yield remainder of timestamp
SYS_SLEEP Sleep until messaged or signaled
SYS_WAIT Wait for a time or a message
SYS_WRITE Write to an open file
SYS_IOCTL Perform an IOCtl Call
SYS_READDIR Read from an open directory
+SYS_OPENCHILD Open a child entry in a directory
SYS_MKDIR Create a new directory
SYS_SYMLINK Create a symbolic link
SYS_GETACL Get an ACL Value
} tConfigCommand;
// === IMPORTS ===
+extern void Arch_LoadBootModules();
extern int Modules_LoadBuiltins();
-//extern int PCI_Install();
-extern void DMA_Install();
+extern void Modules_SetBuiltinParams(char *Name, char *ArgString);
extern void Debug_SetKTerminal(char *File);
-extern void StartupPrint(char *Str);
// === PROTOTYPES ===
-void System_Init(char *ArgString);
+void System_Init(char *Commandline);
void System_ParseCommandLine(char *ArgString);
+void System_ExecuteCommandLine(void);
void System_ParseVFS(char *Arg);
+void System_ParseModuleArgs(char *Arg);
void System_ParseSetting(char *Arg);
-void System_ExecuteScript();
+void System_ExecuteScript(void);
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
+ {"module", 1,2, 00, Module_LoadFile, {(Uint)"",0}}, // Load a module from a file
+ {"spawn", 1,1, 00, 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
+ {"mount", 3,4, 00, VFS_Mount, {(Uint)"",0}}, // Mount a device
+ {"symlink", 2,2, 00, VFS_Symlink, {0}}, // Create a Symbolic Link
+ {"mkdir", 1,1, 00, VFS_MkDir, {0}}, // Create a Directory
+ {"open", 1,2, 00, VFS_Open, {VFS_OPENFLAG_READ,0}}, // Open a file
+ {"close", 1,1, 01, VFS_Close, {0}}, // Close an open file
+ {"ioctl", 3,3, 03, VFS_IOCtl, {0}}, // Call an IOCtl
{"", 0,0, 0, NULL, {0}}
};
// === GLOBALS ===
char *gsConfigScript = "/Acess/Conf/BootConf.cfg";
+char *argv[32];
+ int argc;
// === CODE ===
-void System_Init(char *ArgString)
+void System_Init(char *CommandLine)
{
+ // Parse Kernel's Command Line
+ System_ParseCommandLine(CommandLine);
- // - Parse Kernel's Command Line
- System_ParseCommandLine(ArgString);
+ // Initialise modules
+ Log_Log("Config", "Initialising builtin modules...");
+ Modules_LoadBuiltins();
+ Arch_LoadBootModules();
+
+ System_ExecuteCommandLine();
// - Execute the Config Script
Log_Log("Config", "Executing config script...");
*/
void System_ParseCommandLine(char *ArgString)
{
- char *argv[32];
- int argc;
int i;
char *str;
// Check for the end of the string
if(*str == '\0') { argc--; break;}
argv[argc] = str;
- while(*str && *str != ' ')
- {
- /*if(*str == '"') {
- while(*str && !(*str == '"' && str[-1] != '\\'))
- str ++;
- }*/
- str++;
+ if(*str == '"') {
+ while(*str && !(*str == '"' && str[-1] != '\\'))
+ str ++;
+ }
+ else {
+ while(*str && *str != ' ')
+ str++;
}
if(*str == '\0') break; // Check for EOS
*str = '\0'; // Cap off argument string
if(argc < 32)
argc ++; // Count last argument
- // --- Parse Arguments ---
+ // --- Parse Arguments (Pass 1) ---
for( i = 1; i < argc; i++ )
{
- if( argv[i][0] == '/' )
- System_ParseVFS( argv[i] );
- else
+ switch(argv[i][0])
+ {
+ // --- VFS ---
+ // Ignored on this pass
+ case '/':
+ break;
+
+ // --- Module Paramaters ---
+ // -VTerm:Width=640,Height=480,Scrollback=2
+ case '-':
+ System_ParseModuleArgs( argv[i] );
+ break;
+ // --- Config Options ---
+ // SCRIPT=/Acess/Conf/BootConf.cfg
+ default:
System_ParseSetting( argv[i] );
+ break;
+ }
+ }
+}
+
+void System_ExecuteCommandLine(void)
+{
+ int i;
+ for( i = 1; i < argc; i++ )
+ {
+ switch(argv[i][0])
+ {
+ // --- VFS ---
+ // Mount /System=ext2:/Devices/ATA/A1
+ // Symlink /Acess=/System/Acess2
+ case '/':
+ System_ParseVFS( argv[i] );
+ break;
+ }
}
}
}
}
+/**
+ * \biref Parse a module argument string
+ */
+void System_ParseModuleArgs(char *Arg)
+{
+ char *name, *args;
+ int i;
+
+ // Remove '-'
+ name = Arg + 1;
+
+ // Find the start of the args
+ i = strpos(name, ':');
+ if( i == -1 ) {
+ Log_Warning("Config", "Module spec with no arguments");
+ #if 1
+ return ;
+ #else
+ i = strlen(name);
+ args = name + i;
+ #endif
+ }
+ else {
+ name[i] = '\0';
+ args = name + i + 1;
+ }
+
+ Log_Log("Config", "Setting boot parameters for '%s' to '%s'", name, args);
+ Modules_SetBuiltinParams(name, args);
+}
+
/**
* \fn void System_ParseSetting(char *Arg)
*/
/**
* \fn void System_ExecuteScript()
+ * \brief Reads and parses the boot configuration script
*/
-void System_ExecuteScript()
+void System_ExecuteScript(void)
{
int fp;
int fLen = 0;
return;
}
- // Read into memory buffer
+ // Get length
VFS_Seek(fp, 0, SEEK_END);
fLen = VFS_Tell(fp);
VFS_Seek(fp, 0, SEEK_SET);
+ // Read into memory buffer
fData = malloc(fLen+1);
VFS_Read(fp, fLen, fData);
fData[fLen] = '\0';
}
free( file->Lines[i].Parts );
}
+
+ // Free data
free( file );
free( fData );
}
extern void Proc_Start();
extern tThread *Proc_GetCurThread();
extern int Proc_Clone(Uint *Err, Uint Flags);
+extern void Proc_CallFaultHandler(tThread *Thread);
// === PROTOTYPES ===
void Threads_Init();
{0}, // Saved State
{0}, // VM State
- 0, {0}, {0}, // Signal State
+ 0, 0, // Current Fault, Fault Handler
NULL, NULL, // Messages, Last Message
DEFAULT_QUANTUM, DEFAULT_QUANTUM, // Quantum, Remaining
new->NumTickets = cur->NumTickets;
// Set Signal Handlers
- new->CurSignal = 0;
- if(Flags & CLONE_VM)
- memset(new->SignalHandlers, 0, sizeof(new->SignalHandlers));
- else
- memcpy(new->SignalHandlers, cur->SignalHandlers, sizeof(new->SignalHandlers));
- memset(&new->SignalState, 0, sizeof(tTaskState));
+ new->CurFaultNum = 0;
+ new->FaultHandler = cur->FaultHandler;
for( i = 0; i < NUM_CFG_ENTRIES; i ++ )
{
int initStatus = t->Status;
int ret;
- if(initStatus != THREAD_STAT_ZOMBIE)
+ if(initStatus != THREAD_STAT_ZOMBIE) {
while(t->Status == initStatus) {
Threads_Yield();
}
+ }
ret = t->RetStatus;
switch(t->Status)
RELEASE( &giThreadListLock );
}
-#if 0
/**
- * \fn void Threads_SetSignalHandler(int Num, void *Handler)
+ * \fn void Threads_SetFaultHandler(Uint Handler)
* \brief Sets the signal handler for a signal
*/
-void Threads_SetSignalHandler(int Num, void *Handler)
-{
- if(Num < 0 || Num >= NSIG) return;
-
- gCurrentThread->SignalHandlers[Num] = Handler;
+void Threads_SetFaultHandler(Uint Handler)
+{
+ Log_Log("Threads", "Threads_SetFaultHandler: Handler = %p", Handler);
+ Proc_GetCurThread()->FaultHandler = Handler;
}
/**
- * \fn void Threads_SendSignal(int TID, int Num)
- * \brief Send a signal to a thread
+ * \fn void Threads_Fault(int Num)
+ * \brief Calls a fault handler
*/
-void Threads_SendSignal(int TID, int Num)
+void Threads_Fault(int Num)
{
- tThread *thread = Proc_GetThread(TID);
- void *handler;
+ tThread *thread = Proc_GetCurThread();
+
+ Log_Log("Threads", "Threads_Fault: thread = %p", thread);
if(!thread) return ;
- handler = thread->SignalHandlers[Num];
+ Log_Log("Threads", "Threads_Fault: thread->FaultHandler = %p", thread->FaultHandler);
- // Panic?
- if(handler == SIG_ERR) {
- Proc_Kill(TID);
+ switch(thread->FaultHandler)
+ {
+ case 0: // Panic?
+ Threads_Kill(thread, -1);
+ HALT();
return ;
- }
- // Dump Core?
- if(handler == -2) {
- Proc_Kill(TID);
+ case 1: // Dump Core?
+ Threads_Kill(thread, -1);
+ HALT();
return ;
}
- // Ignore?
- if(handler == -2) return;
-
- // Check the type and handle if the thread is already in a signal
- if(thread->CurSignal != 0) {
- if(Num < _SIGTYPE_FATAL)
- Proc_Kill(TID);
- } else {
- while(thread->CurSignal != 0)
- Proc_Yield();
- }
+
+ // Double Fault? Oh, F**k
+ if(thread->CurFaultNum != 0) {
+ Threads_Kill(thread, -1); // For now, just kill
+ HALT();
}
- //TODO:
+ thread->CurFaultNum = Num;
+
+ Proc_CallFaultHandler(thread);
}
-#endif
// --- Process Structure Access Functions ---
tPID Threads_GetPID()
*/
void Threads_SegFault(tVAddr Addr)
{
- //Threads_SendSignal( Proc_GetCurThread()->TID, SIGSEGV );
Warning("Thread #%i committed a segfault at address %p", Proc_GetCurThread()->TID, Addr);
- Threads_Exit( 0, -1 );
+ Threads_Fault( 1 );
+ //Threads_Exit( 0, -1 );
}
// === EXPORTS ===
/**
* \fn Uint64 VFS_WriteAt(int FD, Uint64 Offset, Uint64 Length, void *Buffer)
- * \brief Write data to a file at a given offset (atomic)
+ * \brief Write data to a file at a given offset
*/
Uint64 VFS_WriteAt(int FD, Uint64 Offset, Uint64 Length, void *Buffer)
{
h = VFS_GetHandle(FD);
if(!h) return -1;
+ //Log_Debug("VFS", "VFS_Seek: (fd=0x%x, Offset=0x%llx, Whence=%i)",
+ // FD, Offset, Whence);
+
// Set relative to current position
if(Whence == 0) {
h->Position += Offset;
return -1;
}
+
+/**
+ * \brief Open a file from an open directory
+ */
+int VFS_OpenChild(Uint *Errno, int FD, char *Name, Uint Mode)
+{
+ tVFS_Handle *h;
+ tVFS_Node *node;
+ int i;
+
+ // Get handle
+ h = VFS_GetHandle(FD);
+ if(h == NULL) {
+ Log_Warning("VFS", "VFS_OpenChild - Invalid file handle 0x%x", FD);
+ if(Errno) *Errno = EINVAL;
+ LEAVE('i', -1);
+ return -1;
+ }
+
+ // Check for directory
+ if( !(h->Node->Flags & VFS_FFLAG_DIRECTORY) ) {
+ Log_Warning("VFS", "VFS_OpenChild - Passed handle is not a directory", FD);
+ if(Errno) *Errno = ENOTDIR;
+ LEAVE('i', -1);
+ return -1;
+ }
+
+ // Find Child
+ node = h->Node->FindDir(h->Node, Name);
+ if(!node) {
+ if(Errno) *Errno = ENOENT;
+ LEAVE('i', -1);
+ return -1;
+ }
+
+ i = 0;
+ i |= (Mode & VFS_OPENFLAG_EXEC) ? VFS_PERM_EXECUTE : 0;
+ i |= (Mode & VFS_OPENFLAG_READ) ? VFS_PERM_READ : 0;
+ i |= (Mode & VFS_OPENFLAG_WRITE) ? VFS_PERM_WRITE : 0;
+
+ // Permissions Check
+ if( !VFS_CheckACL(node, i) ) {
+ if(node->Close) node->Close( node );
+ Log_Notice("VFS", "VFS_OpenChild - Permissions Failed");
+ if(Errno) *Errno = EACCES;
+ LEAVE('i', -1);
+ return -1;
+ }
+
+ // Check for a user open
+ if(Mode & VFS_OPENFLAG_USER)
+ {
+ // Allocate Buffer
+ if( MM_GetPhysAddr( (Uint)gaUserHandles ) == 0 )
+ {
+ Uint addr, size;
+ size = CFGINT(CFG_VFS_MAXFILES) * sizeof(tVFS_Handle);
+ for(addr = 0; addr < size; addr += 0x1000)
+ MM_Allocate( (Uint)gaUserHandles + addr );
+ memset( gaUserHandles, 0, size );
+ }
+ // Get a handle
+ for(i=0;i<CFGINT(CFG_VFS_MAXFILES);i++)
+ {
+ if(gaUserHandles[i].Node) continue;
+ gaUserHandles[i].Node = node;
+ gaUserHandles[i].Position = 0;
+ gaUserHandles[i].Mode = Mode;
+ LEAVE('i', i);
+ return i;
+ }
+ }
+ else
+ {
+ // Allocate space if not already
+ if( MM_GetPhysAddr( (Uint)gaKernelHandles ) == 0 )
+ {
+ Uint addr, size;
+ size = MAX_KERNEL_FILES * sizeof(tVFS_Handle);
+ for(addr = 0; addr < size; addr += 0x1000)
+ MM_Allocate( (Uint)gaKernelHandles + addr );
+ memset( gaKernelHandles, 0, size );
+ }
+ // Get a handle
+ for(i=0;i<MAX_KERNEL_FILES;i++)
+ {
+ if(gaKernelHandles[i].Node) continue;
+ gaKernelHandles[i].Node = node;
+ gaKernelHandles[i].Position = 0;
+ gaKernelHandles[i].Mode = Mode;
+ LEAVE('x', i|VFS_KERNEL_FLAG);
+ return i|VFS_KERNEL_FLAG;
+ }
+ }
+
+ Log_Error("VFS", "VFS_OpenChild - Out of handles");
+ if(Errno) *Errno = ENFILE;
+ LEAVE('i', -1);
+ return -1;
+}
+
/**
* \fn void VFS_Close(int FD)
* \brief Closes an open file handle
// Get handle
h = VFS_GetHandle(FD);
if(h == NULL) {
- Warning("Invalid file handle passed to VFS_Close, 0x%x\n", FD);
+ Log_Warning("VFS", "Invalid file handle passed to VFS_Close, 0x%x\n", FD);
return;
}
{
tVFS_Handle *h;
+ //Log_Debug("VFS", "VFS_GetHandle: (FD=0x%x)", FD);
+
if(FD < 0) return NULL;
if(FD & VFS_KERNEL_FLAG) {
}
if(h->Node == NULL) return NULL;
+ //Log_Debug("VFS", "VFS_GetHandle: RETURN %p", h);
return h;
}
MODULES = Storage/ATA Storage/FDD
MODULES += Network/NE2000
MODULES += Display/VESA
-#MODULES += Display/BochsGA
+MODULES += Display/BochsGA
MODULES += Filesystems/Ext2
MODULES += Filesystems/FAT
MODULES += IPStack
int giBGA_BufferFormat = 0;\r
tVideo_IOCtl_Pos gBGA_CursorPos = {-1,-1};\r
Uint *gBGA_Framebuffer;\r
-tBGA_Mode gpBGA_CurrentMode;\r
+const tBGA_Mode *gpBGA_CurrentMode;\r
const tBGA_Mode gBGA_Modes[] = {\r
- {},\r
- {640,480,32, 0, 640*480*4},\r
- {800,600,32, 0, 800*600*4},\r
- {1024,768,32, 0, 1024*768*4}\r
+ {640,480,32, 640*480*4},\r
+ {800,600,32, 800*600*4},\r
+ {1024,768,32, 1024*768*4}\r
};\r
#define BGA_MODE_COUNT (sizeof(gBGA_Modes)/sizeof(gBGA_Modes[0]))\r
\r
}\r
\r
// Map Framebuffer to hardware address\r
- gBGA_Framebuffer = (void *) MM_MapHWPage(VBE_DISPI_LFB_PHYSICAL_ADDRESS, 768); // 768 pages (3Mb)\r
+ gBGA_Framebuffer = (void *) MM_MapHWPages(VBE_DISPI_LFB_PHYSICAL_ADDRESS, 768); // 768 pages (3Mb)\r
\r
return MODULE_ERR_OK;\r
}\r
void BGA_Uninstall()\r
{\r
DevFS_DelDevice( &gBGA_DriverStruct );\r
- MM_UnmapHWPage( VBE_DISPI_LFB_PHYSICAL_ADDRESS, 768 );\r
+ MM_UnmapHWPages( VBE_DISPI_LFB_PHYSICAL_ADDRESS, 768 );\r
}\r
\r
/**\r
\r
// Check Mode\r
if(giBGA_CurrentMode == -1) {\r
- LEAVE('i', -1);\r
- return -1;\r
+ Log_Notice("BGA", "Setting video mode to #0 (640x480x32)");\r
+ BGA_int_UpdateMode(0); // Mode Zero is 640x480\r
}\r
\r
// Text Mode\r
case VIDEO_BUFFMT_TEXT:\r
{\r
tVT_Char *chars = Buffer;\r
- int pitch = gpBGA_CurrentMode->width * giVT_CharWidth;\r
- int x, y;\r
+ int x, y; // Characters/Rows\r
+ int widthInChars = gpBGA_CurrentMode->width/giVT_CharWidth;\r
Uint32 *dest;\r
\r
off /= sizeof(tVT_Char);\r
- dest = (void*)gBGA_Framebuffer;\r
- x = (off % gpBGA_CurrentMode->width) * giVT_CharWidth;\r
- y = (off / gpBGA_CurrentMode->width) * giVT_CharHeight;\r
+ len /= sizeof(tVT_Char);\r
+ \r
+ x = (off % widthInChars);\r
+ y = (off / widthInChars);\r
\r
// Sanity Check\r
- if(y > gpBGA_CurrentMode->height) {\r
+ if(y > gpBGA_CurrentMode->height / giVT_CharHeight) {\r
LEAVE('i', 0);\r
return 0;\r
}\r
\r
- dest += y * pitch;\r
- dest += x * giVT_CharWidth;\r
- len /= sizeof(tVT_Char);\r
+ dest = (Uint32 *)gBGA_Framebuffer;\r
+ dest += y * gpBGA_CurrentMode->width * giVT_CharHeight;\r
while(len--)\r
{\r
VT_Font_Render(\r
chars->Ch,\r
- dest, pitch,\r
+ dest + x*giVT_CharWidth, gpBGA_CurrentMode->width,\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 ++;\r
+ if( x >= widthInChars ) {\r
x = 0;\r
- y += giVT_CharHeight;\r
- dest += pitch*(giVT_CharHeight-1);\r
+ y ++; // Why am I keeping track of this?\r
+ dest += gpBGA_CurrentMode->width*giVT_CharHeight;\r
}\r
}\r
}\r
// Sanity Check\r
if(id < 0 || id >= BGA_MODE_COUNT) return -1;\r
\r
- // Check if it is a text mode\r
- if( gBGA_Modes[id].flags & MODEFLAG_TEXT )\r
- BGA_int_SetMode(\r
- gBGA_Modes[id].width*giVT_CharWidth,\r
- gBGA_Modes[id].height*giVT_CharHeight);\r
- else // Graphics?\r
- BGA_int_SetMode(\r
- gBGA_Modes[id].width,\r
- gBGA_Modes[id].height);\r
+ BGA_int_SetMode(\r
+ gBGA_Modes[id].width,\r
+ gBGA_Modes[id].height);\r
\r
giBGA_CurrentMode = id;\r
gpBGA_CurrentMode = &gBGA_Modes[id];\r
LogF("Mode %i (%ix%ix%i), ", i, gBGA_Modes[i].width, gBGA_Modes[i].height, gBGA_Modes[i].bpp);\r
#endif\r
\r
- // Check if this mode is the same type as what we want\r
- if( !(gBGA_Modes[i].flags & MODEFLAG_TEXT) != !(info->flags & VIDEO_FLAG_TEXT) )\r
- continue;\r
- \r
// Ooh! A perfect match\r
if(gBGA_Modes[i].width == info->width\r
&& gBGA_Modes[i].height == info->height\r
info->height = gBGA_Modes[best].height;\r
info->bpp = gBGA_Modes[best].bpp;\r
\r
- info->flags = 0;\r
- if(gBGA_Modes[best].flags & MODEFLAG_TEXT)\r
- info->flags |= VIDEO_FLAG_TEXT;\r
- \r
return best;\r
}\r
\r
info->height = gBGA_Modes[info->id].height;\r
info->bpp = gBGA_Modes[info->id].bpp;\r
\r
- info->flags = 0;\r
- if(gBGA_Modes[info->id].flags & MODEFLAG_TEXT)\r
- info->flags |= VIDEO_FLAG_TEXT;\r
- \r
return 1;\r
}\r
\r
* AcessOS 1\r
* Video BIOS Extensions (Vesa) Driver\r
*/\r
-#define DEBUG 1\r
+#define DEBUG 0\r
#define VERSION 0x100\r
\r
#include <acess.h>\r
\r
// === CONSTANTS ===\r
#define FLAG_LFB 0x1\r
+#define VESA_DEFAULT_FRAMEBUFFER (KERNEL_BASE|0xA0000)\r
\r
// === PROTOTYPES ===\r
int Vesa_Install(char **Arguments);\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
+// --- 2D Acceleration Functions --\r
+void Vesa_2D_Fill(void *Ent, Uint16 X, Uint16 Y, Uint16 W, Uint16 H, Uint32 Colour);\r
+void Vesa_2D_Blit(void *Ent, Uint16 DstX, Uint16 DstY, Uint16 SrcX, Uint16 SrcY, Uint16 W, Uint16 H);\r
\r
// === GLOBALS ===\r
MODULE_DEFINE(0, VERSION, Vesa, Vesa_Install, NULL, "PCI", "VM8086", NULL);\r
};\r
tSpinlock glVesa_Lock;\r
tVM8086 *gpVesa_BiosState;\r
- int giVesaCurrentMode = -1;\r
+ int giVesaCurrentMode = 0;\r
int giVesaCurrentFormat = VIDEO_BUFFMT_TEXT;\r
int giVesaDriverId = -1;\r
-char *gVesaFramebuffer = (void*)0xC00A0000;\r
+char *gpVesa_Framebuffer = (void*)VESA_DEFAULT_FRAMEBUFFER;\r
tVesa_Mode *gVesa_Modes;\r
int giVesaModeCount = 0;\r
int giVesaPageCount = 0;\r
+tDrvUtil_Video_2DHandlers gVesa_2DFunctions = {\r
+ NULL,\r
+ Vesa_2D_Fill,\r
+ Vesa_2D_Blit\r
+};\r
\r
//CODE\r
int Vesa_Install(char **Arguments)\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
+ Log_Warning("VESA", "Vesa_Install - VESA/VBE Unsupported (AX = 0x%x)", 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
+ 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
gVesa_Modes[i].fbSize = 0;\r
}\r
\r
+ gVesa_Modes[i].pitch = modeinfo->pitch;\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
+ 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
Uint64 Vesa_Read(tVFS_Node *Node, Uint64 off, Uint64 len, void *buffer)\r
{\r
#if DEBUG >= 2\r
- LogF("Vesa_Read: () - NULL\n");\r
+ Log("Vesa_Read: () - NULL\n");\r
#endif\r
return 0;\r
}\r
// Default Text mode\r
if( giVesaCurrentMode == 0 )\r
{\r
- Uint8 *fb = (Uint8 *)(KERNEL_BASE|0xB8000);\r
- Uint32 *buf = Buffer;\r
+ Uint16 *fb = (Uint16*)(KERNEL_BASE|0xB8000);\r
+ tVT_Char *chars = Buffer;\r
int rem;\r
\r
+ Length /= sizeof(tVT_Char);\r
+ Offset /= sizeof(tVT_Char);\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
+ if( Offset + Length > 25*80 ) {\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
+ LOG("fb = %p", fb);\r
+ for(rem = Length; rem --; fb ++, chars++)\r
{\r
- if( *buf < 0x80 )\r
- *fb = *buf & 0x7F;\r
+ if( chars->Ch < 0x80 )\r
+ *fb = chars->Ch & 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
+ *fb |= (chars->FGCol & 0x888) == 0x888 ? 0x8 : 0;\r
+ *fb |= (chars->FGCol & 0x700) > 0x300 ? 0x4 : 0;\r
+ *fb |= (chars->FGCol & 0x070) > 0x030 ? 0x2 : 0;\r
+ *fb |= (chars->FGCol & 0x007) > 0x003 ? 0x1 : 0;\r
+ *fb |= (chars->BGCol & 0x888) == 0x888 ? 0x80 : 0;\r
+ *fb |= (chars->BGCol & 0x700) > 0x300 ? 0x40 : 0;\r
+ *fb |= (chars->BGCol & 0x070) > 0x030 ? 0x20 : 0;\r
+ *fb |= (chars->BGCol & 0x007) > 0x003 ? 0x10 : 0;\r
+ //LOG("%08x (%03x,%03x) = %04x",\r
+ // chars->Ch, chars->BGCol, chars->FGCol, *fb);\r
}\r
- Length /= sizeof(tVT_Char);\r
Length *= sizeof(tVT_Char);\r
LEAVE('X', Length);\r
return Length;\r
case VIDEO_BUFFMT_TEXT:\r
{\r
tVT_Char *chars = Buffer;\r
- int pitch = gVesa_Modes[giVesaCurrentMode].width * giVT_CharWidth;\r
+ int pitch = gVesa_Modes[giVesaCurrentMode].width;\r
+ int widthInChars = gVesa_Modes[giVesaCurrentMode].width/giVT_CharWidth;\r
+ int heightInChars = gVesa_Modes[giVesaCurrentMode].height/giVT_CharHeight;\r
int x, y;\r
- Uint32 *dest;\r
- int rem;\r
+ Uint32 *dest = (void*)gpVesa_Framebuffer;\r
+ int i;\r
\r
+ Length /= sizeof(tVT_Char);\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
+ LOG("gVesa_Modes[%i].width = %i", giVesaCurrentMode, gVesa_Modes[giVesaCurrentMode].width);\r
+ x = Offset % widthInChars;\r
+ y = Offset / widthInChars;\r
+ LOG("(x,y) = (%i,%i) = [%i,%i]", x, y, x * giVT_CharWidth, y * giVT_CharHeight * pitch);\r
+ LOG("(w,h) = (%i,%i) = [%i,%i]",\r
+ (int)(Length % widthInChars),\r
+ (int)(Length / widthInChars),\r
+ (int)((Length % widthInChars) * giVT_CharWidth),\r
+ (int)((Length / widthInChars) * giVT_CharHeight * pitch)\r
+ );\r
\r
// Sanity Check\r
- if(y > gVesa_Modes[giVesaCurrentMode].height) {\r
+ if(y > heightInChars) {\r
LEAVE('i', 0);\r
return 0;\r
}\r
\r
- dest += y * pitch;\r
+ if( Offset + Length > heightInChars*widthInChars ) {\r
+ Log_Debug("VESA", "%i + %i > %i*%i (%i)",\r
+ (int)Offset, (int)Length, heightInChars, widthInChars, heightInChars*widthInChars);\r
+ Length = heightInChars*widthInChars - Offset;\r
+ Log_Notice("VESA", "Clipping write size to %i characters", (int)Length);\r
+ }\r
+ \r
+ dest += y * giVT_CharHeight * pitch;\r
dest += x * giVT_CharWidth;\r
- for( rem = Length / sizeof(tVT_Char); rem--; )\r
+ \r
+ LOG("dest = %p", dest);\r
+ \r
+ for( i = 0; i < Length; i++ )\r
{\r
VT_Font_Render(\r
chars->Ch,\r
- dest, pitch,\r
+ dest + x*giVT_CharWidth, 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 ++;\r
+ if( x >= widthInChars ) {\r
x = 0;\r
- y += giVT_CharHeight;\r
- dest += pitch*(giVT_CharHeight-1);\r
+ y ++;\r
+ dest += pitch*giVT_CharHeight;\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
+ Uint8 *destBuf = (Uint8*) ((Uint)gpVesa_Framebuffer + (Uint)Offset);\r
\r
if(gVesa_Modes[giVesaCurrentMode].fbSize < Offset+Length)\r
{\r
LOG("BGA Framebuffer updated");\r
}\r
break;\r
+ \r
+ case VIDEO_BUFFMT_2DSTREAM:\r
+ Length = DrvUtil_Video_2DStream(\r
+ NULL, // Single framebuffer, so Ent is unused\r
+ Buffer, Length, &gVesa_2DFunctions, sizeof(gVesa_2DFunctions)\r
+ );\r
+ break;\r
+ \r
default:\r
LEAVE('i', -1);\r
return -1;\r
int Vesa_Ioctl(tVFS_Node *Node, int ID, void *Data)\r
{\r
int ret;\r
+ //Log_Debug("VESA", "Vesa_Ioctl: (Node=%p, ID=%i, Data=%p)", Node, ID, Data);\r
switch(ID)\r
{\r
case DRV_IOCTL_TYPE: return DRV_TYPE_VIDEO;\r
\r
case VIDEO_IOCTL_SETBUFFORMAT:\r
ret = giVesaCurrentFormat;\r
- if(Data) giVesaCurrentFormat = *(int*)Data;\r
+ if(Data) {\r
+ //Log_Log("VESA", "Buffer mode to %i", *(int*)Data);\r
+ giVesaCurrentFormat = *(int*)Data;\r
+ }\r
return ret;\r
\r
+ case VIDEO_IOCTL_SETCURSOR: // Set cursor position\r
+ return 0;\r
+ \r
case VIDEO_IOCTL_REQLFB: // Request Linear Framebuffer\r
return 0;\r
}\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
+ Log_Log("VESA", "Setting mode to %i", mode);\r
\r
// Sanity Check values\r
if(mode < 0 || mode > giVesaModeCount) return -1;\r
VM8086_Int(gpVesa_BiosState, 0x10);\r
\r
// Map Framebuffer\r
- MM_UnmapHWPages((tVAddr)gVesaFramebuffer, giVesaPageCount);\r
+ if( (tVAddr)gpVesa_Framebuffer != VESA_DEFAULT_FRAMEBUFFER )\r
+ MM_UnmapHWPages((tVAddr)gpVesa_Framebuffer, giVesaPageCount);\r
giVesaPageCount = (gVesa_Modes[mode].fbSize + 0xFFF) >> 12;\r
- gVesaFramebuffer = (void*)MM_MapHWPages(gVesa_Modes[mode].framebuffer, giVesaPageCount);\r
+ gpVesa_Framebuffer = (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
+ Log_Log("VESA", "Framebuffer (Phys) = 0x%x", gVesa_Modes[mode].framebuffer);\r
+ Log_Log("VESA", "Framebuffer (Virt) = 0x%x", gpVesa_Framebuffer);\r
\r
// Record Mode Set\r
giVesaCurrentMode = mode;\r
data->bpp = gVesa_Modes[data->id].bpp;\r
return 1;\r
}\r
+\r
+// ------------------------\r
+// --- 2D Accelleration ---\r
+// ------------------------\r
+void Vesa_2D_Fill(void *Ent, Uint16 X, Uint16 Y, Uint16 W, Uint16 H, Uint32 Colour)\r
+{\r
+ int scrnwidth = gVesa_Modes[giVesaCurrentMode].width;\r
+ Uint32 *buf = (Uint32*)gpVesa_Framebuffer + Y*scrnwidth + X;\r
+ while( H -- ) {\r
+ memsetd(buf, Colour, W);\r
+ buf += scrnwidth;\r
+ }\r
+}\r
+\r
+void Vesa_2D_Blit(void *Ent, Uint16 DstX, Uint16 DstY, Uint16 SrcX, Uint16 SrcY, Uint16 W, Uint16 H)\r
+{\r
+ int scrnwidth = gVesa_Modes[giVesaCurrentMode].width;\r
+ int dst = DstY*scrnwidth + DstX;\r
+ int src = SrcY*scrnwidth + SrcX;\r
+ int tmp;\r
+ \r
+ //Log("Vesa_2D_Blit: (Ent=%p, DstX=%i, DstY=%i, SrcX=%i, SrcY=%i, W=%i, H=%i)",\r
+ // Ent, DstX, DstY, SrcX, SrcY, W, H);\r
+ \r
+ if(SrcX + W > scrnwidth)\r
+ W = scrnwidth - SrcX;\r
+ if(DstX + W > scrnwidth)\r
+ W = scrnwidth - DstX;\r
+ if(SrcY + H > gVesa_Modes[giVesaCurrentMode].height)\r
+ H = gVesa_Modes[giVesaCurrentMode].height - SrcY;\r
+ if(DstY + H > gVesa_Modes[giVesaCurrentMode].height)\r
+ H = gVesa_Modes[giVesaCurrentMode].height - DstY;\r
+ \r
+ if( dst > src ) {\r
+ // Reverse copy\r
+ dst += H*scrnwidth;\r
+ src += H*scrnwidth;\r
+ while( H -- ) {\r
+ dst -= scrnwidth;\r
+ src -= scrnwidth;\r
+ tmp = W;\r
+ for( tmp = W; tmp --; ) {\r
+ *((Uint32*)gpVesa_Framebuffer + dst + tmp) = *((Uint32*)gpVesa_Framebuffer + src + tmp);\r
+ }\r
+ }\r
+ }\r
+ else {\r
+ // Normal copy is OK\r
+ while( H -- ) {\r
+ memcpyd((Uint32*)gpVesa_Framebuffer + dst, (Uint32*)gpVesa_Framebuffer + src, W);\r
+ dst += scrnwidth;\r
+ src += scrnwidth;\r
+ }\r
+ }\r
+}\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
+ * 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
* \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 DEBUG 0\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 USE_LFN 1 //!< Enables the use of Long File Names\r
#define SUPPORT_WRITE 0\r
\r
#include <acess.h>\r
if(Cluster) *Cluster = cluster;\r
}\r
\r
+ LOG("cluster = %08x", cluster);\r
+ \r
// Bounds Checking (Used to spot corruption)\r
if(cluster > disk->ClusterCount + 2)\r
{\r
return 1;\r
}\r
\r
+ LOG("addr = 0x%llx", addr);\r
// Read Sector\r
if(VFS_ReadAt(disk->fileHandle, addr, 512, Buffer) != 512)\r
{\r
\r
if(FAT_int_ReadDirSector(Node, ID/16, fileinfo))\r
{\r
+ LOG("End of chain, end of dir");\r
LEAVE('n');\r
return NULL;\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
+ LOG("fileinfo[%i].name[0] = 0x%x", a, (Uint8)fileinfo[a].name[0]);\r
\r
// Check if this is the last entry\r
if( fileinfo[a].name[0] == '\0' ) {\r
// Check for empty entry\r
if( (Uint8)fileinfo[a].name[0] == 0xE5 ) {\r
LOG("Empty Entry");\r
+ #if 0 // Stop on empty entry?\r
+ LEAVE('n');\r
+ return NULL; // Stop\r
+ #else\r
LEAVE('p', VFS_SKIP);\r
return VFS_SKIP; // Skip\r
+ #endif\r
}\r
\r
#if USE_LFN\r
{\r
// Remove LFN if it does not apply\r
if(lfnId != i) lfn[0] = '\0';\r
+ #else\r
+ if(fileinfo[i&0xF].attrib == ATTR_LFN) continue;\r
#endif\r
// Get Real Filename\r
FAT_int_ProperFilename(tmpName, fileinfo[i&0xF].name);\r
#
OBJ = main.o files.o
+EXTRA = files.c
NAME = InitRD
-include ../Makefile.tpl
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 "libc.so.1" "../../../Usermode/Libraries/libc.so"
File "libgcc.so" "../../../Usermode/Libraries/libgcc.so"
}
Dir "Conf" {
int dataLength;
if(Length < sizeof(tIPv4Header)) return;
+ #if 0
//Log_Log("IPv4", "Version = %i", hdr->Version);
- Log_Log("IPv4", "HeaderLength = %i", hdr->HeaderLength);
- Log_Log("IPv4", "DiffServices = %i", hdr->DiffServices);
+ //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", "Destination = %i.%i.%i.%i",
hdr->Destination.B[0], hdr->Destination.B[1],
hdr->Destination.B[2], hdr->Destination.B[3] );
-
+ #endif
+
// Check that the version IS IPv4
if(hdr->Version != 4) {
Log_Log("IPv4", "hdr->Version(%i) != 4", hdr->Version);
return;
Log("[IPv6 ] hdr = {");
- Log("[IPv6 ] .Version = %i", (hdr->Head >> (20+8)) & 0xF );
- Log("[IPv6 ] .TrafficClass = %i", (hdr->Head >> (20)) & 0xFF );
- Log("[IPv6 ] .FlowLabel = %i", hdr->Head & 0xFFFFF );
+ Log("[IPv6 ] .Version = %i", (hdr->Head >> (20+8)) & 0xF );
+ Log("[IPv6 ] .TrafficClass = %i", (hdr->Head >> (20)) & 0xFF );
+ Log("[IPv6 ] .FlowLabel = %i", hdr->Head & 0xFFFFF );
Log("[IPv6 ] .PayloadLength = 0x%04x", ntohs(hdr->PayloadLength) );
- Log("[IPv6 ] .NextHeader = 0x%02x", hdr->NextHeader );
- Log("[IPv6 ] .HopLimit = 0x%02x", hdr->HopLimit );
- Log("[IPv6 ] .Source = %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", hdr->Source );
- Log("[IPv6 ] .Destination = %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", hdr->Destination );
+ Log("[IPv6 ] .NextHeader = 0x%02x", hdr->NextHeader );
+ Log("[IPv6 ] .HopLimit = 0x%02x", hdr->HopLimit );
+ Log("[IPv6 ] .Source = %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", hdr->Source );
+ Log("[IPv6 ] .Destination = %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", hdr->Destination );
Log("[IPv6 ] }");
}
* Acess2 IP Stack
* - TCP Handling
*/
+#define DEBUG 1
#include "ipstack.h"
#include "ipv4.h"
#include "tcp.h"
#define TCP_MIN_DYNPORT 0xC000
#define TCP_MAX_HALFOPEN 1024 // Should be enough
+#define TCP_MAX_PACKET_SIZE 1024
+#define TCP_WINDOW_SIZE 0x2000
+#define TCP_RECIEVE_BUFFER_SIZE 0x4000
+
// === PROTOTYPES ===
void TCP_Initialise();
void TCP_StartConnection(tTCPConnection *Conn);
IPv4_RegisterCallback(IP4PROT_TCP, TCP_GetPacket);
}
-/**
- * \brief Open a connection to another host using TCP
- * \param Conn Connection structure
- */
-void TCP_StartConnection(tTCPConnection *Conn)
-{
- tTCPHeader hdr;
-
- hdr.SourcePort = Conn->LocalPort;
- hdr.DestPort = Conn->RemotePort;
- Conn->NextSequenceSend = rand();
- hdr.SequenceNumber = Conn->NextSequenceSend;
- hdr.DataOffset = (sizeof(tTCPHeader)/4) << 4;
- hdr.Flags = TCP_FLAG_SYN;
- hdr.WindowSize = 0xFFFF; // Max
- hdr.Checksum = 0; // TODO
- hdr.UrgentPointer = 0;
-
- TCP_SendPacket( Conn, sizeof(tTCPHeader), &hdr );
- return ;
-}
-
/**
* \brief Sends a packet from the specified connection, calculating the checksums
* \param Conn Connection
Log_Log("TCP", "SourcePort = %i, DestPort = %i",
ntohs(hdr->SourcePort), ntohs(hdr->DestPort));
+/*
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", "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 )
{
case 6: conn->RemoteIP.v6 = *(tIPv6*)Address; break;
}
+ conn->RecievedBuffer = RingBuffer_Create( TCP_RECIEVE_BUFFER_SIZE );
+
conn->NextSequenceRcv = ntohl( hdr->SequenceNumber ) + 1;
conn->NextSequenceSend = rand();
// Create node
conn->Node.NumACLs = 1;
conn->Node.ACLs = &gVFS_ACL_EveryoneRW;
+ conn->Node.ImplPtr = conn;
conn->Node.ImplInt = srv->NextID ++;
conn->Node.Read = TCP_Client_Read;
conn->Node.Write = TCP_Client_Write;
hdr->SourcePort = htons(srv->Port);
hdr->DataOffset = (sizeof(tTCPHeader)/4) << 4;
TCP_SendPacket( conn, sizeof(tTCPHeader), hdr );
-
+ conn->NextSequenceSend ++;
return ;
}
}
tTCPStoredPacket *pkt;
int dataLen;
- Connection->State = TCP_ST_OPEN;
if(Header->Flags & TCP_FLAG_SYN) {
- Connection->NextSequenceRcv = Header->SequenceNumber + 1;
+ Connection->NextSequenceRcv = ntohl(Header->SequenceNumber) + 1;
+ }
+
+ if( Connection->State == TCP_ST_SYN_SENT )
+ {
+ if( (Header->Flags & (TCP_FLAG_SYN|TCP_FLAG_ACK)) == (TCP_FLAG_SYN|TCP_FLAG_ACK) ) {
+
+ Header->DestPort = Header->SourcePort;
+ Header->SourcePort = htons(Connection->LocalPort);
+ Header->AcknowlegementNumber = htonl(Connection->NextSequenceRcv);
+ Header->SequenceNumber = htonl(Connection->NextSequenceSend);
+ Header->WindowSize = htons(TCP_WINDOW_SIZE);
+ Header->Flags = TCP_FLAG_ACK;
+ Header->DataOffset = (sizeof(tTCPHeader)/4) << 4;
+ Log_Log("TCP", "ACKing SYN-ACK");
+ TCP_SendPacket( Connection, sizeof(tTCPHeader), Header );
+ Connection->State = TCP_ST_OPEN;
+ }
}
// Get length of data
Log_Log("TCP", "Conn %p, Packet 0x%x ACKed", Connection, Header->AcknowlegementNumber);
}
- if(dataLen == 0) return ;
+ // TODO: Check what to do here
+ if(Header->Flags & TCP_FLAG_FIN) {
+ if( Connection->State == TCP_ST_FIN_SENT ) {
+ Connection->State = TCP_ST_FINISHED;
+ return ;
+ }
+ else {
+ Connection->State = TCP_ST_FINISHED;
+ Header->DestPort = Header->SourcePort;
+ Header->SourcePort = htons(Connection->LocalPort);
+ Header->AcknowlegementNumber = htonl(Connection->NextSequenceRcv);
+ Header->SequenceNumber = htonl(Connection->NextSequenceSend);
+ Header->Flags = TCP_FLAG_ACK;
+ TCP_SendPacket( Connection, sizeof(tTCPHeader), Header );
+ return ;
+ }
+ }
+
+ if(dataLen == 0) {
+ Log_Log("TCP", "Empty Packet");
+ return ;
+ }
// NOTES:
// Flags
memcpy(pkt->Data, (Uint8*)Header + (Header->DataOffset>>4)*4, dataLen);
// Is this packet the next expected packet?
+ // TODO: Fix this to check if the packet is in the window.
if( pkt->Sequence != Connection->NextSequenceRcv )
{
tTCPStoredPacket *tmp, *prev = NULL;
{
// Ooh, Goodie! Add it to the recieved list
TCP_INT_AppendRecieved(Connection, pkt);
- if(dataLen)
- Connection->NextSequenceRcv += dataLen;
- else
- Connection->NextSequenceRcv += 1;
+ free(pkt);
+ Log_Log("TCP", "0x%08x += %i", Connection->NextSequenceRcv, dataLen);
+ Connection->NextSequenceRcv += dataLen;
// 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) + dataLen;
- Header->SequenceNumber = ntohl(Connection->NextSequenceSend);
- Header->Flags &= TCP_FLAG_SYN;
- Header->Flags = TCP_FLAG_ACK;
+ // ACK Packet
+ Header->DestPort = Header->SourcePort;
+ Header->SourcePort = htons(Connection->LocalPort);
+ Header->AcknowlegementNumber = htonl(Connection->NextSequenceRcv);
+ Header->SequenceNumber = htonl(Connection->NextSequenceSend);
+ Header->WindowSize = htons(TCP_WINDOW_SIZE);
+ Header->Flags &= TCP_FLAG_SYN; // Eliminate all flags save for SYN
+ Header->Flags |= TCP_FLAG_ACK; // Add ACK
+ Log_Log("TCP", "Sending ACK for 0x%08x", Connection->NextSequenceRcv);
TCP_SendPacket( Connection, sizeof(tTCPHeader), Header );
+ //Connection->NextSequenceSend ++;
}
}
void TCP_INT_AppendRecieved(tTCPConnection *Connection, tTCPStoredPacket *Pkt)
{
LOCK( &Connection->lRecievedPackets );
- if(Connection->RecievedPackets)
+ if(Connection->RecievedBuffer->Length + Pkt->Length > Connection->RecievedBuffer->Space )
{
- Connection->RecievedPacketsTail->Next = Pkt;
- Connection->RecievedPacketsTail = Pkt;
- }
- else
- {
- Connection->RecievedPackets = Pkt;
- Connection->RecievedPacketsTail = Pkt;
+ Log_Error("TCP", "Buffer filled, packet dropped (%s)",
+ // TCP_INT_DumpConnection(Connection)
+ ""
+ );
+ return ;
}
+
+ RingBuffer_Write( Connection->RecievedBuffer, Pkt->Data, Pkt->Length );
+
RELEASE( &Connection->lRecievedPackets );
}
// Looks like we found one
TCP_INT_AppendRecieved(Connection, pkt);
- Connection->NextSequenceRcv ++;
+ Connection->NextSequenceRcv += pkt->Length;
+ free(pkt);
}
}
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->Port = 0;
srv->NextID = 0;
srv->Connections = NULL;
+ srv->ConnectionsTail = NULL;
+ srv->NewConnections = NULL;
srv->Next = NULL;
srv->Node.Flags = VFS_FFLAG_DIRECTORY;
srv->Node.Size = -1;
tTCPListener *srv = Node->ImplPtr;
tTCPConnection *conn;
char *ret;
+
+ ENTER("pNode iPos", Node, Pos);
Log_Log("TCP", "Thread %i waiting for a connection", Threads_GetTID());
for(;;)
// Increment the new list (the current connection is still on the
- // normal list
+ // normal list)
conn = srv->NewConnections;
srv->NewConnections = conn->Next;
+ LOG("conn = %p", conn);
+ LOG("srv->Connections = %p", srv->Connections);
+ LOG("srv->NewConnections = %p", srv->NewConnections);
+ LOG("srv->ConnectionsTail = %p", srv->ConnectionsTail);
+
RELEASE( &srv->lConnections );
ret = malloc(9);
- itoa(ret, Node->ImplInt, 16, 8, '0');
- Log("TCP_Server_ReadDir: RETURN '%s'", ret);
+ itoa(ret, conn->Node.ImplInt, 16, 8, '0');
+ Log_Log("TCP", "Thread %i got '%s'", Threads_GetTID(), ret);
+ LEAVE('s', ret);
return ret;
}
char tmp[9];
int id = atoi(Name);
+ ENTER("pNode sName", Node, Name);
+
// Sanity Check
itoa(tmp, id, 16, 8, '0');
- if(strcmp(tmp, Name) != 0) return NULL;
+ if(strcmp(tmp, Name) != 0) {
+ LOG("'%s' != '%s' (%08x)", Name, tmp, id);
+ LEAVE('n');
+ return NULL;
+ }
+
+ Log_Debug("TCP", "srv->Connections = %p", srv->Connections);
+ Log_Debug("TCP", "srv->NewConnections = %p", srv->NewConnections);
+ Log_Debug("TCP", "srv->ConnectionsTail = %p", srv->ConnectionsTail);
// Search
LOCK( &srv->lConnections );
for(conn = srv->Connections;
- conn && conn->Node.ImplInt != id;
- conn = conn->Next);
+ conn;
+ conn = conn->Next)
+ {
+ LOG("conn->Node.ImplInt = %i", conn->Node.ImplInt);
+ if(conn->Node.ImplInt == id) break;
+ }
RELEASE( &srv->lConnections );
// If not found, ret NULL
- if(!conn) return NULL;
+ if(!conn) {
+ LOG("Connection %i not found", id);
+ LEAVE('n');
+ return NULL;
+ }
// Return node
+ LEAVE('p', &conn->Node);
return &conn->Node;
}
conn->State = TCP_ST_CLOSED;
conn->Interface = Interface;
- conn->LocalPort = 0;
- conn->RemotePort = 0;
+ conn->LocalPort = -1;
+ conn->RemotePort = -1;
memset( &conn->RemoteIP, 0, sizeof(conn->RemoteIP) );
conn->Node.ImplPtr = conn;
conn->Node.IOCtl = TCP_Client_IOCtl;
conn->Node.Close = TCP_Client_Close;
+ conn->RecievedBuffer = RingBuffer_Create( TCP_RECIEVE_BUFFER_SIZE );
+
LOCK(&glTCP_OutbountCons);
conn->Next = gTCP_OutbountCons;
gTCP_OutbountCons = conn;
Uint64 TCP_Client_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
{
tTCPConnection *conn = Node->ImplPtr;
- tTCPStoredPacket *pkt;
+ char *destbuf = Buffer;
+ size_t len;
- Log("TCP_Client_Read: (Length=%i)", Length);
+ ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);
+ LOG("conn = %p", conn);
+ LOG("conn->State = %i", conn->State);
// Check if connection is open
- if( conn->State != TCP_ST_OPEN ) return 0;
+ while( conn->State == TCP_ST_HALFOPEN || conn->State == TCP_ST_SYN_SENT )
+ Threads_Yield();
+ if( conn->State != TCP_ST_OPEN ) {
+ LEAVE('i', 0);
+ return 0;
+ }
// Poll packets
for(;;)
- {
+ {
// Lock list and check if there is a packet
LOCK( &conn->lRecievedPackets );
- if( conn->RecievedPackets == NULL ) {
+ if( conn->RecievedBuffer->Length == 0 ) {
// If not, release the lock, yield and try again
RELEASE( &conn->lRecievedPackets );
Threads_Yield();
continue;
}
- // Get packet pointer
- pkt = conn->RecievedPackets;
- conn->RecievedPackets = pkt->Next;
+ // Attempt to read all `Length` bytes
+ len = RingBuffer_Read( destbuf, conn->RecievedBuffer, Length );
+
// Release the lock (we don't need it any more)
RELEASE( &conn->lRecievedPackets );
-
- Log("TCP_Client_Read: pkt->Length = %i", pkt->Length);
-
- // Copy Data
- if(Length > pkt->Length) Length = pkt->Length;
- memcpy(Buffer, pkt->Data, Length);
-
- // Free packet and return
- free(pkt);
- return Length;
+
+ LEAVE('i', len);
+ return len;
}
}
+/**
+ * \brief Send a data packet on a connection
+ */
+void TCP_INT_SendDataPacket(tTCPConnection *Connection, size_t Length, void *Data)
+{
+ char buf[sizeof(tTCPHeader)+Length];
+ tTCPHeader *packet = (void*)buf;
+
+ packet->SourcePort = htons(Connection->LocalPort);
+ packet->DestPort = htons(Connection->RemotePort);
+ packet->DataOffset = (sizeof(tTCPHeader)/4)*16;
+ packet->WindowSize = TCP_WINDOW_SIZE;
+
+ packet->AcknowlegementNumber = htonl(Connection->NextSequenceRcv);
+ packet->SequenceNumber = htonl(Connection->NextSequenceSend);
+ packet->Flags = TCP_FLAG_PSH|TCP_FLAG_ACK; // Hey, ACK if you can!
+
+ memcpy(packet->Options, Data, Length);
+
+ TCP_SendPacket( Connection, sizeof(tTCPHeader)+Length, packet );
+
+ Connection->NextSequenceSend += Length;
+}
+
+/**
+ * \brief Send some bytes on a connection
+ */
Uint64 TCP_Client_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
{
- return 0;
+ tTCPConnection *conn = Node->ImplPtr;
+ size_t rem = Length;
+
+ ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);
+
+ // Check if connection is open
+ while( conn->State == TCP_ST_HALFOPEN || conn->State == TCP_ST_SYN_SENT )
+ Threads_Yield();
+ if( conn->State != TCP_ST_OPEN ) {
+ LEAVE('i', 0);
+ return 0;
+ }
+
+ while( rem > TCP_MAX_PACKET_SIZE )
+ {
+ TCP_INT_SendDataPacket(conn, TCP_MAX_PACKET_SIZE, Buffer);
+ Buffer += TCP_MAX_PACKET_SIZE;
+ }
+
+ TCP_INT_SendDataPacket(conn, rem, Buffer);
+
+ LEAVE('i', Length);
+ return Length;
+}
+
+/**
+ * \brief Open a connection to another host using TCP
+ * \param Conn Connection structure
+ */
+void TCP_StartConnection(tTCPConnection *Conn)
+{
+ tTCPHeader hdr;
+
+ Conn->State = TCP_ST_SYN_SENT;
+
+ hdr.SourcePort = htons(Conn->LocalPort);
+ hdr.DestPort = htons(Conn->RemotePort);
+ Conn->NextSequenceSend = rand();
+ hdr.SequenceNumber = htonl(Conn->NextSequenceSend);
+ hdr.DataOffset = (sizeof(tTCPHeader)/4) << 4;
+ hdr.Flags = TCP_FLAG_SYN;
+ hdr.WindowSize = htons(TCP_WINDOW_SIZE); // Max
+ hdr.Checksum = 0; // TODO
+ hdr.UrgentPointer = 0;
+
+ TCP_SendPacket( Conn, sizeof(tTCPHeader), &hdr );
+
+ Conn->NextSequenceSend ++;
+ Conn->State = TCP_ST_SYN_SENT;
+ return ;
}
/**
return 0;
case 7: // Connect
- if(conn->LocalPort == -1)
+ if(conn->LocalPort == 0xFFFF)
conn->LocalPort = TCP_GetUnusedPort();
if(conn->RemotePort == -1)
return 0;
void TCP_Client_Close(tVFS_Node *Node)
{
- free(Node->ImplPtr);
+ tTCPConnection *conn = Node->ImplPtr;
+ tTCPHeader packet;
+
+ packet.SourcePort = htons(conn->LocalPort);
+ packet.DestPort = htons(conn->RemotePort);
+ packet.DataOffset = (sizeof(tTCPHeader)/4)*16;
+ packet.WindowSize = TCP_WINDOW_SIZE;
+
+ packet.AcknowlegementNumber = 0;
+ packet.SequenceNumber = htonl(conn->NextSequenceSend);
+ packet.Flags = TCP_FLAG_FIN;
+
+ conn->State = TCP_ST_FIN_SENT;
+
+ TCP_SendPacket( conn, sizeof(tTCPHeader), &packet );
+
+ while( conn->State == TCP_ST_FIN_SENT ) Threads_Yield();
+
+ free(conn);
}
tInterface *Interface; //!< Listening Interface
tVFS_Node Node; //!< Node
- int NextSequenceSend; //!< Next sequence value for outbound packets
- int NextSequenceRcv; //!< Next expected sequence value for inbound
+ Uint32 NextSequenceSend; //!< Next sequence value for outbound packets
+ Uint32 NextSequenceRcv; //!< Next expected sequence value for inbound
/**
* \brief Non-ACKed packets
/**
* \brief Unread Packets
- * \note Double ended list (fifo)
+ * \note Ring buffer
* \{
*/
tSpinlock lRecievedPackets;
- tTCPStoredPacket *RecievedPackets; //!< Unread Packets
- tTCPStoredPacket *RecievedPacketsTail; //!< Unread Packets (End of list)
+ tRingBuffer *RecievedBuffer;
/**
* \}
*/
enum eTCPConnectionState
{
TCP_ST_CLOSED,
+ TCP_ST_SYN_SENT,
TCP_ST_HALFOPEN,
- TCP_ST_OPEN
+ TCP_ST_OPEN,
+ TCP_ST_FIN_SENT,
+ TCP_ST_FINISHED
};
#endif
LOG("ent = %i", ent);
gATA_BusMasterBase = PCI_GetBAR4( ent );
if( gATA_BusMasterBase == 0 ) {
- Warning("It seems that there is no Bus Master Controller on this machine. Get one");
+ Log_Warning("ATA", "It seems that there is no Bus Master Controller on this machine. Get one");
+ // TODO: Use PIO mode instead
LEAVE('i', MODULE_ERR_NOTNEEDED);
return MODULE_ERR_NOTNEEDED;
}
#
#
-CFLAGS += -Wall -fno-builtin -fno-stack-protector
+CFLAGS += -Wall -fno-builtin -fno-stack-protector -g
LDFLAGS +=
+DEPFILES := $(OBJ:%.o=%.d)
+
.PHONY : all clean install
all: $(BIN)
$(BIN): $(OBJ)
@echo --- $(LD) -o $@
- @$(LD) $(LDFLAGS) -o $@ $(OBJ) -Map Map.txt
- @objdump -d $(BIN) > $(BIN).dsm
+ @$(LD) -g $(LDFLAGS) -o $@ $(OBJ) -Map Map.txt
+ @objdump -d -S $(BIN) > $(BIN).dsm
$(OBJ): %.o: %.c
@echo --- GCC -o $@
- @$(CC) $(CFLAGS) $(CPPFLAGS) -c $? -o $@
+ @$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
+ @$(CC) -M -MT $@ $(CPPFLAGS) $< -o $*.d
+
+-include $(DEPFILES)
/*
- * Acess2 GUI Shell
+ * Acess2 GUI Test App
* - By John Hodge (thePowersGang)
*/
#include <axwin/axwin.h>
// === CODE ===
int main(int argc, char *argv[])
-{
+{
+ AxWin_Register("Terminal");
+
// Create Window
- ghMenubarWindow = AxWin_CreateWindow(0, 0, -1, -1, WINFLAG_NOBORDER, Menubar_HandleMessage);
+ //ghMenubarWindow = AxWin_CreateWindow(0, 0, -1, -1, WINFLAG_NOBORDER, Menubar_HandleMessage);
AxWin_MessageLoop();
CPPFLAGS += -I../include
-DIR = Apps/AxWin/1.0
-BIN = ../AxWinWM
-OBJ = main.o helpers.o commandline.o video.o messages.o
+DIR := Apps/AxWin/1.0
+BIN := ../AxWinWM
+OBJ := main.o helpers.o commandline.o video.o
+OBJ += messages.o interface.o wm.o decorator.o
+OBJ += image.o
-include ../../Makefile.tpl
#include <stdint.h>
#include "wm.h"
+#include "image.h"
+//#include "font.h"
// === GLOBALS ===
extern char *gsTerminalDevice;
// === Functions ===
extern void memset32(void *ptr, uint32_t val, size_t count);
-
+// --- Video ---
+extern void Video_Update(void);
+extern void Video_FillRect(short X, short Y, short W, short H, uint32_t Color);
+extern void Video_DrawRect(short X, short Y, short W, short H, uint32_t Color);
+extern void Video_DrawText(short X, short Y, short W, short H, void *Font, int Point, uint32_t Color, char *Text);
+// --- Debug Hack ---
+extern void _SysDebug(const char *Format, ...);
#endif
--- /dev/null
+/*
+ * Acess GUI (AxWin) Version 2
+ * By John Hodge (thePowersGang)
+ *
+ * Widget Decorator
+ */
+#include "common.h"
+#include "wm.h"
+
+#define BOX_BGCOLOUR 0xC0C0C0
+#define BOX_BORDER 0xA0A0A0
+#define BUTTON_BGCOLOUR 0xD0D0D0
+#define BUTTON_BORDER 0xF0F0F0
+#define TEXT_COLOUR 0x000000
+
+// === CODE ===
+void Decorator_RenderWidget(tElement *Element)
+{
+ _SysDebug("Decorator_RenderWidget: (Element={Type:%i,(%i,%i) %ix%i})",
+ Element->Type,
+ Element->CachedX, Element->CachedY,
+ Element->CachedW, Element->CachedH
+ );
+
+ switch(Element->Type)
+ {
+ case ELETYPE_NONE:
+ case ELETYPE_BOX: break;
+
+ case ELETYPE_TABBAR: // TODO: Moar
+ case ELETYPE_TOOLBAR:
+ Video_DrawRect(
+ Element->CachedX, Element->CachedY,
+ Element->CachedW, Element->CachedH,
+ BOX_BORDER
+ );
+ Video_FillRect(
+ Element->CachedX+1, Element->CachedY+1,
+ Element->CachedW-2, Element->CachedH-2,
+ BOX_BGCOLOUR
+ );
+ break;
+
+ case ELETYPE_SPACER:
+ Video_FillRect(
+ Element->CachedX+3, Element->CachedY+3,
+ Element->CachedW-6, Element->CachedH-6,
+ BOX_BORDER
+ );
+ break;
+
+ case ELETYPE_BUTTON:
+ Video_FillRect(
+ Element->CachedX+1, Element->CachedY+1,
+ Element->CachedW-2, Element->CachedH-2,
+ BUTTON_BORDER
+ );
+ Video_DrawRect(
+ Element->CachedX, Element->CachedY,
+ Element->CachedW-1, Element->CachedH-1,
+ BUTTON_BORDER
+ );
+ break;
+
+ case ELETYPE_TEXT:
+ Video_DrawText(
+ Element->CachedX+1, Element->CachedY+1,
+ Element->CachedW-2, Element->CachedH-2,
+ NULL,
+ 10,
+ TEXT_COLOUR,
+ Element->Text
+ );
+ break;
+ }
+}
--- /dev/null
+/*
+ * Acess GUI (AxWin) Version 2
+ * By John Hodge (thePowersGang)
+ */
+#include "common.h"
+
+// === GLOBALS ==
+ int giInterface_Width = 0;
+tElement *gpInterface_Sidebar;
+tElement *gpInterface_MainArea;
+tElement *gpInterface_HeaderBar;
+tElement *gpInterface_TabBar;
+tElement *gpInterface_TabContent;
+
+// === CODE ===
+void Interface_Init(void)
+{
+ tElement *area;
+ tElement *btn, *text;
+
+ giInterface_Width = giScreenWidth/16;
+
+ WM_SetFlags(NULL, 0);
+
+ // -- Create Sidebar --
+ gpInterface_Sidebar = WM_CreateElement(NULL, ELETYPE_TOOLBAR, ELEFLAG_VERTICAL);
+ WM_SetSize( gpInterface_Sidebar, giInterface_Width );
+
+ // --- Top segment ---
+ area = WM_CreateElement(gpInterface_Sidebar, ELETYPE_BOX, ELEFLAG_VERTICAL);
+ // ---- Menu Button ----
+ btn = WM_CreateElement(area, ELETYPE_BUTTON, ELEFLAG_NOSTRETCH);
+ WM_SetSize(btn, giInterface_Width);
+ //text = WM_CreateElement(btn, ELETYPE_IMAGE, ELEFLAG_SCALE);
+ //WM_SetText(text, "asset://LogoSmall.sif");
+ text = WM_CreateElement(btn, ELETYPE_TEXT, 0);
+ WM_SetText(text, "Acess");
+
+ // ---- Plain <hr/> style spacer ----
+ WM_CreateElement(area, ELETYPE_SPACER, 0);
+
+ // Windows Go Here
+
+ // --- Bottom Segment ---
+ area = WM_CreateElement(gpInterface_Sidebar, ELETYPE_BOX, ELEFLAG_VERTICAL|ELEFLAG_ALIGN_END);
+
+ // ---- Plain <hr/> style spacer ----
+ WM_CreateElement(area, ELETYPE_SPACER, 0);
+
+ // ---- Version String ----
+ text = WM_CreateElement(area, ELETYPE_TEXT, ELEFLAG_WRAP);
+ WM_SetText(text, "AxWin 1.0");
+
+ // -- Create Main Area and regions within --
+ gpInterface_MainArea = WM_CreateElement(NULL, ELETYPE_BOX, ELEFLAG_VERTICAL);
+ gpInterface_HeaderBar = WM_CreateElement(gpInterface_MainArea, ELETYPE_BOX, 0);
+ gpInterface_TabBar = WM_CreateElement(gpInterface_MainArea, ELETYPE_TABBAR, 0);
+ gpInterface_TabContent = WM_CreateElement(gpInterface_MainArea, ELETYPE_BOX, 0);
+}
+
+void Interface_Update(void)
+{
+ giInterface_Width = giScreenWidth/16;
+ WM_SetSize( gpInterface_Sidebar, giInterface_Width );
+}
+
+void Interface_Render(void)
+{
+
+ Video_FillRect(
+ 0, 0,
+ giInterface_Width, giScreenHeight,
+ 0xDDDDDD);
+
+ Video_Update();
+}
// === IMPORTS ===
extern void ParseCommandline(int argc, char *argv[]);
-extern void Video_Setup();
+extern void Video_Setup(void);
+extern void WM_Update(void);
+extern void Messages_PollIPC(void);
+extern void Interface_Init(void);
// === GLOBALS ===
char *gsTerminalDevice = NULL;
ParseCommandline(argc, argv);
if( gsTerminalDevice == NULL ) {
- gsTerminalDevice = "/Devices/VTerm/7";
+ gsTerminalDevice = "/Devices/VTerm/6";
}
Video_Setup();
+ Interface_Init();
+
+ WM_Update();
// Main Loop
for(;;)
{
switch(Msg->ID)
{
+ #if 0
case MSG_SREQ_PING:
- Msg->ID = MSG_SRSP_PONG;
- Respond(ID, sizeof(Msg->ID), Msg);
+ Msg->ID = MSG_SRSP_VERSION;
+ Msg->Size = 2;
+ Msg->Data[0] = 0;
+ Msg->Data[1] = 1;
+ *(uint16_t*)&Msg->Data[2] = -1;
+ Messages_RespondIPC(ID, sizeof(Msg->ID), Msg);
break;
+ #endif
default:
fprintf(stderr, "WARNING: Unknown message %i from %i (%p)\n", Msg->ID, ID, Respond);
_SysDebug("WARNING: Unknown message %i from %i (%p)\n", Msg->ID, ID, Respond);
#include <acess/devices/terminal.h>
// === PROTOTYPES ===
-void Video_Setup();
-void Video_Update();
+void Video_Setup(void);
+void Video_Update(void);
+void Video_FillRect(short X, short Y, short W, short H, uint32_t Color);
// === GLOBALS ===
// === CODE ===
-void Video_Setup()
+void Video_Setup(void)
{
int tmpInt;
Video_Update();
}
-void Video_Update()
+void Video_Update(void)
{
- seek(giTerminalFD, 0, SEEK_SET);
+ //seek(giTerminalFD, 0, SEEK_SET);
+ seek(giTerminalFD, 0, 1);
write(giTerminalFD, giScreenWidth*giScreenHeight*4, gpScreenBuffer);
}
+
+void Video_FillRect(short X, short Y, short W, short H, uint32_t Color)
+{
+ uint32_t *buf = gpScreenBuffer + Y*giScreenWidth + X;
+
+ _SysDebug("Video_FillRect: (X=%i, Y=%i, W=%i, H=%i, Color=%08x)",
+ X, Y, W, H, Color);
+
+ if(W < 0 || X < 0 || X >= giScreenWidth) return ;
+ if(X + W > giScreenWidth) W = giScreenWidth - X;
+
+ if(H < 0 || Y < 0 || Y >= giScreenHeight) return ;
+ if(Y + H > giScreenHeight) H = giScreenHeight - Y;
+
+ while( H -- )
+ {
+ memset32( buf, Color, W );
+ buf += giScreenWidth;
+ }
+}
+
+void Video_DrawRect(short X, short Y, short W, short H, uint32_t Color)
+{
+ Video_FillRect(X, Y, W, 1, Color);
+ Video_FillRect(X, Y+H-1, W, 1, Color);
+ Video_FillRect(X, Y, 1, H, Color);
+ Video_FillRect(X+W-1, Y, 1, H, Color);
+}
+
+void Video_DrawText(short X, short Y, short W, short H, void *Font, int Point, uint32_t Color, char *Text)
+{
+ // TODO!
+}
--- /dev/null
+/*
+ * Acess GUI (AxWin) Version 2
+ * By John Hodge (thePowersGang)
+ *
+ * Window Manager and Widget Control
+ */
+#include "common.h"
+#include <stdlib.h>
+#include <strings.h>
+#include "wm.h"
+
+// === IMPORTS ===
+extern void Decorator_RenderWidget(tElement *Element);
+
+// === PROTOTYPES ===
+tElement *WM_CreateElement(tElement *Parent, int Type, int Flags);
+void WM_UpdateMinDims(tElement *Element);
+void WM_SetFlags(tElement *Element, int Flags);
+void WM_SetSize(tElement *Element, int Size);
+void WM_SetText(tElement *Element, char *Text);
+void WM_UpdateDimensions(tElement *Element, int Pass);
+void WM_UpdatePosition(tElement *Element);
+void WM_RenderWidget(tElement *Element);
+void WM_Update(void);
+
+// === GLOBALS ===
+tElement gWM_RootElement;
+struct {
+ void (*Init)(tElement *This);
+ void (*UpdateFlags)(tElement *This);
+ void (*UpdateSize)(tElement *This);
+ void (*UpdateText)(tElement *This);
+} gaWM_WidgetTypes[MAX_ELETYPES] = {
+ {NULL, NULL, NULL, NULL}, // NULL
+ {NULL, NULL, NULL, NULL} // Box
+};
+
+// === CODE ===
+// --- Widget Creation and Control ---
+tElement *WM_CreateElement(tElement *Parent, int Type, int Flags)
+{
+ tElement *ret;
+
+ ret = calloc(sizeof(tElement), 1);
+ if(!ret) return NULL;
+
+ // Prepare
+ ret->Type = Type;
+ if(Parent == NULL) Parent = &gWM_RootElement;
+ ret->Parent = Parent;
+ ret->Flags = Flags;
+
+ // Append to parent's list
+ ret->NextSibling = Parent->LastChild;
+ Parent->LastChild = ret;
+ if(!Parent->FirstChild) Parent->FirstChild = ret;
+
+ ret->PaddingL = 2;
+ ret->PaddingR = 2;
+ ret->PaddingT = 2;
+ ret->PaddingB = 2;
+
+ if( gaWM_WidgetTypes[Type].Init )
+ gaWM_WidgetTypes[Type].Init(ret);
+
+ WM_UpdateMinDims(ret->Parent);
+
+ return ret;
+}
+
+/**
+ * \brief Alter an element's flags
+ */
+void WM_SetFlags(tElement *Element, int Flags)
+{
+ // Permissions are handled in the message handler
+ if(!Element) {
+ gWM_RootElement.Flags = Flags;
+ return ;
+ }
+
+ Element->Flags = Flags;
+ return ;
+}
+
+void WM_SetSize(tElement *Element, int Size)
+{
+ if(!Element) return ;
+ Element->FixedWith = Size;
+ return ;
+}
+
+void WM_SetText(tElement *Element, char *Text)
+{
+ if(!Element) return ;
+ if(Element->Text) free(Element->Text);
+ Element->Text = strdup(Text);
+
+ switch(Element->Type)
+ {
+ case ELETYPE_IMAGE:
+ if(Element->Data) free(Element->Data);
+ Element->Data = Image_Load( Element->Text );
+ if(!Element->Data) {
+ Element->Flags &= ~ELEFLAG_FIXEDSIZE;
+ return ;
+ }
+
+ //Element->Flags |= ELEFLAG_FIXEDSIZE;
+ Element->CachedW = ((tImage*)Element->Data)->Width;
+ Element->CachedH = ((tImage*)Element->Data)->Height;
+
+ if(Element->Parent && Element->Parent->Flags & ELEFLAG_VERTICAL) {
+ Element->MinCross = ((tImage*)Element->Data)->Width;
+ Element->MinWith = ((tImage*)Element->Data)->Height;
+ }
+ else {
+ Element->MinWith = ((tImage*)Element->Data)->Width;
+ Element->MinCross = ((tImage*)Element->Data)->Height;
+ }
+ break;
+ }
+
+ return ;
+}
+
+// --- Pre-Rendering ---
+/**
+ * \brief Updates the dimensions of an element
+ *
+ * The dimensions of an element are calculated from the parent's
+ * cross dimension (the side at right angles to the alignment) sans some
+ * padding.
+ */
+void WM_UpdateDimensions(tElement *Element, int Pass)
+{
+ tElement *child;
+ int nChildren = 0;
+ int nFixed = 0;
+ int maxCross = 0;
+ int fixedSize = 0;
+ int fullCross, dynWith;
+
+ _SysDebug("%p -> Flags = 0x%x", Element, Element->Flags);
+ _SysDebug("%p ->CachedH = %i, ->PaddingT = %i, ->PaddingB = %i",
+ Element, Element->CachedH, Element->PaddingT, Element->PaddingB
+ );
+ _SysDebug("%p ->CachedW = %i, ->PaddingL = %i, ->PaddingR = %i",
+ Element, Element->CachedW, Element->PaddingL, Element->PaddingR
+ );
+
+ // Pass 1
+ for( child = Element->FirstChild; child; child = child->NextSibling )
+ {
+ if( child->Flags & ELEFLAG_ABSOLUTEPOS )
+ continue ;
+
+ _SysDebug("%p,%p ->FixedWith = %i", Element, child, child->FixedWith);
+ if( child->FixedWith )
+ {
+ nFixed ++;
+ fixedSize += child->FixedWith;
+ }
+
+ if( child->FixedCross && maxCross < child->FixedCross )
+ maxCross = child->FixedCross;
+ if( child->MinCross && maxCross < child->MinCross )
+ maxCross = child->MinCross;
+ nChildren ++;
+ }
+
+ _SysDebug("%p - nChildren = %i, nFixed = %i", Element, nChildren, nFixed);
+ if( nChildren > nFixed ) {
+ if( Element->Flags & ELEFLAG_VERTICAL )
+ dynWith = Element->CachedH - Element->PaddingT
+ - Element->PaddingB;
+ else
+ dynWith = Element->CachedW - Element->PaddingL
+ - Element->PaddingR;
+ dynWith -= fixedSize;
+ if( dynWith < 0 ) return ;
+ dynWith /= nChildren - nFixed;
+ _SysDebug("%p - dynWith = %i", Element, dynWith);
+ }
+
+ if( Element->Flags & ELEFLAG_VERTICAL )
+ fullCross = Element->CachedW - Element->PaddingL - Element->PaddingR;
+ else
+ fullCross = Element->CachedH - Element->PaddingT - Element->PaddingB;
+
+ _SysDebug("%p - fullCross = %i", Element, fullCross);
+
+ // Pass 2 - Set sizes and recurse
+ for( child = Element->FirstChild; child; child = child->NextSibling )
+ {
+ int cross, with;
+
+ _SysDebug("%p,%p ->MinCross = %i", Element, child, child->MinCross);
+
+
+ // --- Cross Size ---
+ if( child->FixedCross )
+ cross = child->FixedCross;
+ // Expand to fill?
+ // TODO: Extra flag so options are (Expand, Equal, Wrap)
+ else if( child->Flags & ELEFLAG_NOEXPAND )
+ cross = child->MinCross;
+ else
+ cross = fullCross;
+ _SysDebug("%p,%p - cross = %i", Element, child, cross);
+ if( Element->Flags & ELEFLAG_VERTICAL )
+ child->CachedW = cross;
+ else
+ child->CachedH = cross;
+
+ // --- With Size ---
+ if( child->FixedWith)
+ with = child->FixedWith;
+ else if( child->Flags & ELEFLAG_NOSTRETCH )
+ with = child->MinWith;
+ else
+ with = dynWith;
+ _SysDebug("%p,%p - with = %i", Element, child, with);
+ if( Element->Flags & ELEFLAG_VERTICAL )
+ child->CachedH = with;
+ else
+ child->CachedW = with;
+
+ WM_UpdateDimensions(child, 0);
+ }
+}
+
+/**
+ * \brief Updates the position of an element
+ *
+ * The parent element sets the positions of its children
+ */
+void WM_UpdatePosition(tElement *Element)
+{
+ tElement *child;
+ int x, y;
+
+ if( Element->Flags & ELEFLAG_NORENDER ) return ;
+
+ _SysDebug("Element=%p{PaddingL:%i, PaddingT:%i}",
+ Element, Element->PaddingL, Element->PaddingT);
+
+ // Initialise
+ x = Element->CachedX + Element->PaddingL;
+ y = Element->CachedY + Element->PaddingT;
+
+ // Update each child
+ for(child = Element->FirstChild; child; child = child->NextSibling)
+ {
+ child->CachedX = x;
+ child->CachedY = y;
+
+ // Set Alignment
+ if( Element->Flags & ELEFLAG_ALIGN_CENTER ) {
+ if(Element->Flags & ELEFLAG_VERTICAL )
+ child->CachedX += Element->CachedW/2 - child->CachedW/2;
+ else
+ child->CachedY += Element->CachedH/2 - child->CachedH/2;
+ }
+ else if( Element->Flags & ELEFLAG_ALIGN_END ) {
+ if(Element->Flags & ELEFLAG_VERTICAL )
+ child->CachedX += Element->CachedW - child->CachedW;
+ else
+ child->CachedY += Element->CachedH - child->CachedH;
+ }
+
+ // Update child's children positions
+ WM_UpdatePosition(child);
+
+ // Increment
+ if(Element->Flags & ELEFLAG_VERTICAL ) {
+ y += child->CachedH + Element->GapSize;
+ }
+ else {
+ x += child->CachedW + Element->GapSize;
+ }
+ }
+
+ _SysDebug("Element %p (%i,%i)",
+ Element, Element->CachedX, Element->CachedY
+ );
+}
+
+
+/**
+ * \brief Update the minimum dimensions of the element
+ * \note Called after a child's minimum dimensions have changed
+ */
+void WM_UpdateMinDims(tElement *Element)
+{
+ tElement *child;
+
+ if(!Element) return;
+
+ Element->MinCross = 0;
+ Element->MinWith = 0;
+
+ for(child = Element->FirstChild; child; child = child->NextSibling)
+ {
+ if( Element->Parent &&
+ (Element->Flags & ELEFLAG_VERTICAL) == (Element->Parent->Flags & ELEFLAG_VERTICAL)
+ )
+ {
+ if(child->FixedCross)
+ Element->MinCross += child->FixedCross;
+ else
+ Element->MinCross += child->MinCross;
+ if(child->FixedWith)
+ Element->MinWith += child->FixedWith;
+ else
+ Element->MinWith += child->MinWith;
+ }
+ else
+ {
+ if(child->FixedCross)
+ Element->MinWith += child->FixedCross;
+ else
+ Element->MinWith += child->MinCross;
+ if(child->FixedWith)
+ Element->MinCross += child->FixedWith;
+ else
+ Element->MinCross += child->MinWith;
+ }
+ }
+
+ // Recurse upwards
+ WM_UpdateMinDims(Element->Parent);
+}
+
+// --- Render ---
+void WM_RenderWidget(tElement *Element)
+{
+ tElement *child;
+
+ if( Element->Flags & ELEFLAG_NORENDER ) return ;
+ if( Element->Flags & ELEFLAG_INVISIBLE ) return ;
+
+ Decorator_RenderWidget(Element);
+
+ for(child = Element->FirstChild; child; child = child->NextSibling)
+ {
+ WM_RenderWidget(child);
+ }
+}
+
+void WM_Update(void)
+{
+ gWM_RootElement.CachedX = 0; gWM_RootElement.CachedY = 0;
+ gWM_RootElement.CachedW = giScreenWidth;
+ gWM_RootElement.CachedH = giScreenHeight;
+ gWM_RootElement.Flags |= ELEFLAG_NOEXPAND|ELEFLAG_ABSOLUTEPOS|ELEFLAG_FIXEDSIZE;
+
+ WM_UpdateDimensions( &gWM_RootElement, 0 );
+ WM_UpdatePosition( &gWM_RootElement );
+ WM_RenderWidget( &gWM_RootElement );
+
+ Video_Update();
+}
typedef struct sElement
{
+ int Type;
+
+ struct sElement *Parent;
+ struct sElement *FirstChild;
+ struct sElement *LastChild;
struct sElement *NextSibling;
- short CachedX;
- short CachedY;
- short CachedW;
- short CachedH;
+ short PaddingL, PaddingR;
+ short PaddingT, PaddingB;
+ short GapSize;
- struct sElement *FirstChild;
+ short FixedWith; // Fixed Long Size attribute (height)
+ short FixedCross; // Fixed Cross Size attribute (width)
+
+ char *Text;
+
+ // -- Attributes maitained by the element code
+ // Not touched by the user
+ short MinWith; // Minimum long size
+ short MinCross; // Minimum cross size
+ void *Data;
+
+ uint32_t Flags;
+
+ // -- Render Cache
+ short CachedX, CachedY;
+ short CachedW, CachedH;
} tElement;
typedef struct sTab
{
+ int Type; // Should be zero, allows a tab to be the parent of an element
+
+ struct sElement *Parent;
+ struct sElement *FirstChild;
+ struct sElement *LastChild;
+
char *Name;
tElement *RootElement;
char Name[];
} tApplication;
+// === CONSTANTS ===
+enum eElementFlags
+{
+ /**
+ * \brief Rendered
+ *
+ * If set, the element will be ignored in calculating sizes and
+ * rendering.
+ */
+ ELEFLAG_NORENDER = 0x001,
+ /**
+ * \brief Element visibility
+ *
+ * If set, the element is not drawn.
+ */
+ ELEFLAG_INVISIBLE = 0x002,
+
+ /**
+ * \brief Position an element absulutely
+ */
+ ELEFLAG_ABSOLUTEPOS = 0x004,
+
+ /**
+ * \brief Fixed size element
+ */
+ ELEFLAG_FIXEDSIZE = 0x008,
+
+ /**
+ * \brief Element "orientation"
+ */
+ ELEFLAG_VERTICAL = 0x010,// ELEFLAG_HORIZONTAL = 0x000,
+ /**
+ * \brief Action for text that overflows
+ */
+ ELEFLAG_WRAP = 0x020,// ELEFLAG_NOWRAP = 0x000,
+ /**
+ * \brief Cross size action
+ *
+ * If this flag is set, the element will only be as large (across
+ * its parent) as is needed to encase the contents of the element.
+ * Otherwise, the element will expand to fill all avaliable space.
+ */
+ ELEFLAG_NOEXPAND = 0x040,
+
+ ELEFLAG_NOSTRETCH = 0x080,
+
+ /**
+ * \brief Center alignment
+ */
+ ELEFLAG_ALIGN_CENTER= 0x100,
+ /**
+ * \brief Right/Bottom alignment
+ */
+ ELEFLAG_ALIGN_END = 0x200
+};
+
+/**
+ */
+enum eElementTypes
+{
+ ELETYPE_NONE,
+
+ ELETYPE_BOX, //!< Content box
+ ELETYPE_TABBAR, //!< Tab Bar
+ ELETYPE_TOOLBAR, //!< Tool Bar
+
+ ELETYPE_BUTTON, //!< Push Button
+ ELETYPE_TEXT, //!< Text
+ ELETYPE_IMAGE, //!< Image
+
+ ELETYPE_SPACER, //!< Visual Spacer
+
+ MAX_ELETYPES = 0x100
+};
+
+// === FUNCTIONS ===
+/**
+ * \brief Create a new element as a child of \a Parent
+ */
+extern tElement *WM_CreateElement(tElement *Parent, int Type, int Flags);
+extern void WM_SetFlags(tElement *Element, int Flags);
+extern void WM_SetSize(tElement *Element, int Size);
+extern void WM_SetText(tElement *Element, char *Text);
+
#endif
while( (ch = fgetc(stdin)) != -1 && ch != '\n' )
{
if(ch == '\b') {
+ if( pos <= 0 ) continue;
pos --;
ret[pos] = '\0';
}
while( (ch = fgetc(stdin)) != -1 && ch != '\n' )
{
if(ch == '\b') {
+ if( pos <= 0 ) continue;
pos --;
ret[pos] = '\0';
}
else if(size < (uint64_t)2048*1024*1024*1024) { // < 2 TiB
printf("%4i GiB ", size>>30);
}
- else { // Greater than 2 TiB
+ else { // Greater than 2 TiB (if your files are larger than this, you are Doing It Wrong [TM])
printf("%4i TiB ", size>>40);
}
} else {
--- /dev/null
+# Project: testsrv
+
+-include ../Makefile.cfg
+
+OBJ = main.o
+BIN = ../testsrv
+
+-include ../Makefile.tpl
+
--- /dev/null
+/*
+ * Acess2 Test Server
+ */
+#include <acess/sys.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/**
+ * \fn int main(int argc, char *argv[])
+ * \brief Entrypoint
+ */
+int main(int argc, char *argv[])
+{
+ int srv = -1;
+ int con = -1;
+ int len;
+ uint16_t port;
+ char buf[8+1];
+ uint8_t data[4096]; // Packet Data
+
+ srv = open("/Devices/ip/1/tcps", OPENFLAG_READ|OPENFLAG_EXEC);
+ if(srv == -1) {
+ fprintf(stderr, "Unable top open TCP server '/Devices/ip/1/tcps'\n");
+ return -1;
+ }
+ port = 80; ioctl(srv, 4, &port); // Set Port
+
+ for(;;)
+ {
+ readdir( srv, buf );
+ printf("Connection '/Devices/ip/1/tcps/%s'\n", buf);
+ con = _SysOpenChild(srv, buf, OPENFLAG_READ|OPENFLAG_WRITE);
+ if(con == -1) {
+ fprintf(stderr, "Wtf! Why didn't this open?\n");
+ return 1;
+ }
+
+ len = read(con, 4096, data);
+ if( len == -1 ) {
+ printf("Connection closed\n");
+ close(con);
+ continue;
+ }
+ if( len != 0 )
+ {
+ printf("Packet Data: (%i bytes)\n", len);
+ printf("%s\n", data);
+ printf("--- EOP ---\n");
+ }
+
+ #define RET_STR "HTTP/1.1 200 OK\r\n"\
+ "Content-Type: text/plain\r\n"\
+ "Content-Length: 92\r\n"\
+ "\r\n"\
+ "<html><head><title>Acess2 Web Server</title></head><body><h1>Hello World!</h1></body></html>\r\n"
+
+ write(con, sizeof(RET_STR), RET_STR);
+
+ close(con);
+ }
+
+ return 0;
+}
ASFLAGS = -felf
CPPFLAGS = -I$(ACESSDIR)/Usermode/include/
-CFLAGS = -Wall -fPIC -fno-builtin -fno-stack-protector $(CPPFLAGS)
-LDFLAGS = -nostdlib -shared -I/Acess/Libs/ld-acess.so -e SoMain -x -L.. -lacess
+CFLAGS = -g -Wall -fPIC -fno-builtin -fno-stack-protector $(CPPFLAGS)
+LDFLAGS = -g -nostdlib -shared -I/Acess/Libs/ld-acess.so -e SoMain -x -L.. -lacess
all: $(BIN)
clean:
- $(RM) $(BIN) $(OBJ)
+ $(RM) $(BIN) $(OBJ) $(BIN).dsm
install: $(BIN)
$(xCP) $(BIN) $(DISTROOT)/Libs/
$(BIN): $(OBJ)
$(LD) $(LDFLAGS) -o $(BIN) $(OBJ)
+ @$(OBJDUMP) -d -S $(BIN) > $(BIN).dsm
%.o: %.c
$(CC) $(CFLAGS) -o $@ -c $<
BIN = ../acess.ld
+.PHONY: all clean install
+
all: ../acess.ld
clean:
$(RM) ../acess.ld
-install:
+install: ../acess.ld
../acess.ld: acess.ld.h
cpp -nostdinc -U i386 -P -C $< -o $@ -DACESSDIR=$(ACESSDIR)
ASFLAGS = -felf
-.PHONY: all clean
+.PHONY: all clean install
all: ../crt0.o
-install:
+install: ../crt0.o
clean:
$(RM) ../crt0.o
\r
#include <stdarg.h>\r
\r
+// === CONSTANTS ===\r
+#define MAX_LOADED_LIBRARIES 64\r
+#define MAX_STRINGS_BYTES 4096\r
+#define SYSTEM_LIB_DIR "/Acess/Libs/"\r
+\r
// === Types ===\r
typedef unsigned int Uint;\r
typedef unsigned char Uint8;\r
typedef signed char Sint8;\r
typedef signed short Sint16;\r
typedef signed long Sint32;\r
+\r
+typedef struct {\r
+ Uint Base;\r
+ char *Name;\r
+} tLoadedLib;\r
+\r
+// === GLOBALS ===\r
+extern tLoadedLib gLoadedLibraries[MAX_LOADED_LIBRARIES];\r
// === Main ===
extern int DoRelocate( Uint base, char **envp, char *Filename );
extern void SysDebugV(char *fmt, ...);\r
extern Uint SysLoadBin(char *path, Uint *entry);\r
extern Uint SysUnloadBin(Uint Base);\r
+extern void SysSetFaultHandler(int (*Hanlder)(int));\r
extern int open(char *filename, int flags);\r
extern void close(int fd);\r
[global _SysExit]\r
[global _SysLoadBin]\r
[global _SysUnloadBin]\r
+[global _SysSetFaultHandler]\r
[global _open]\r
[global _close]\r
\r
int 0xAC\r
pop ebx\r
ret\r
+\r
+_SysSetFaultHandler:\r
+ push ebx\r
+ mov eax, SYS_SETFAULTHANDLER\r
+ mov ebx, [esp+0x8] ; File Descriptor\r
+ int 0xAC\r
+ pop ebx\r
+ ret\r
# define DEBUGS(v...) \r
#endif\r
\r
-// === CONSTANTS ===\r
-#define MAX_LOADED_LIBRARIES 64\r
-#define MAX_STRINGS_BYTES 4096\r
-#define SYSTEM_LIB_DIR "/Acess/Libs/"\r
-\r
// === PROTOTYPES ===\r
Uint IsFileLoaded(char *file);
int GetSymbolFromBase(Uint base, char *name, Uint *ret);\r
\r
-// === GLOABLS ===\r
-struct {\r
- Uint Base;\r
+// === CONSTANTS ===\r
+const struct {\r
+ Uint Value;\r
char *Name;\r
-} gLoadedLibraries[MAX_LOADED_LIBRARIES];\r
+} caLocalExports[] = {\r
+ {gLoadedLibraries, "gLoadedLibraries"}\r
+};\r
+\r
+// === GLOABLS ===\r
+tLoadedLib gLoadedLibraries[MAX_LOADED_LIBRARIES];\r
char gsLoadedStrings[MAX_STRINGS_BYTES];\r
char *gsNextAvailString = gsLoadedStrings;\r
//tLoadLib *gpLoadedLibraries = NULL;\r
{\r
int i;
Uint ret;\r
+ for(i=0;i<sizeof(caLocalExports)/sizeof(caLocalExports[0]);i++)\r
+ {\r
+ if( strcmp(caLocalExports[i].Name, name) == 0 )\r
+ return caLocalExports[i].Value;\r
+ }\r
+ \r
for(i=0;i<sizeof(gLoadedLibraries)/sizeof(gLoadedLibraries[0]);i++)\r
{\r
if(gLoadedLibraries[i].Base == 0) break;\r
int SoMain(Uint base, int arg1)\r
{\r
int ret;\r
- \r
- //SysDebug("SoMain: base = 0x%x", base);\r
- //SysDebug("SoMain: arg1 = 0x%x", arg1);\r
\r
// - Assume that the file pointer will be less than 4096\r
if(base < 0x1000) {\r
@$(LD) $(LDFLAGS) -o $(BIN) $(OBJ)
@$(STRIP) $(BIN)
-%.ao: %.asm syscalls.inc.asm
+%.ao: %.asm syscalls.inc.asm ../../../Kernel/include/syscalls.inc.asm
@echo $(AS) -o $@
@$(AS) $(ASFLAGS) -o $@ $<
SYSCALL1 _exit, SYS_EXIT
SYSCALL2 clone, SYS_CLONE
SYSCALL2 kill, SYS_KILL
-SYSCALL2 signal, SYS_SIGNAL
SYSCALL0 yield, SYS_YIELD
SYSCALL0 sleep, SYS_SLEEP
SYSCALL1 wait, SYS_WAIT
SYSCALL3 execve, SYS_EXECVE
SYSCALL2 SysLoadBin, SYS_LOADBIN
+SYSCALL1 _SysSetFaultHandler, SYS_SETFAULTHANDLER
SYSCALL6 _SysDebug, 0x100
SYSCALL1 chdir, SYS_CHDIR ; char*
SYSCALL3 ioctl, SYS_IOCTL ; int, int, void*
SYSCALL4 _SysMount, SYS_MOUNT ; char*, char*, char*, char*
+
+SYSCALL3 _SysOpenChild, SYS_OPENCHILD
CFLAGS += -Wall
LDFLAGS += -lc -soname libaxwin2.so
-OBJ = main.o messages.o windows.o
+OBJ = main.o messages.o
BIN = ../libaxwin2.so
include ../Makefile.tpl
// === Variables ===
extern int giAxWin_Mode;
+extern int giAxWin_PID;
#endif
* main.c - Library Initialisation
*/
#include "common.h"
+#include <string.h>
// === GLOBALS ===
int giAxWin_Mode = 0;
+ int giAxWin_PID = 0;
// === CODE ===
int SoMain()
{
return 0;
}
+
+int AxWin_Register(const char *Name)
+{
+ tAxWin_Message req;
+ tAxWin_Message *msg;
+ tAxWin_RetMsg *ret;
+ int len = strlen(Name);
+
+ req.ID = MSG_SREQ_REGISTER;
+ req.Size = 1 + (len+1)/4;
+ strcpy(req.Data, Name);
+
+ AxWin_SendMessage(&req);
+
+ for(;;)
+ {
+ msg = AxWin_WaitForMessage();
+
+ if(msg->ID == MSG_SREQ_ADDTAB)
+ {
+ ret = (void*) &msg->Data[0];
+ if( ret->ReqID == MSG_SREQ_REGISTER )
+ break;
+ }
+
+ AxWin_HandleMessage(msg);
+ free(msg);
+ }
+
+ return !!ret->Bool;
+}
+
+tAxWin_Handle AxWin_AddTab(const char *Title)
+{
+ tAxWin_Message req;
+ tAxWin_Message *msg;
+ tAxWin_RetMsg *ret;
+ int len = strlen(Title);
+
+ req.ID = MSG_SREQ_ADDTAB;
+ req.Size = 1 + (len+1)/4;
+ strcpy(req.Data, Title);
+
+ for(;;)
+ {
+ msg = AxWin_WaitForMessage();
+
+ if(msg->ID == MSG_SRSP_RETURN)
+ {
+ ret = (void*) &msg->Data[0];
+ if( ret->ReqID == MSG_SREQ_ADDTAB )
+ break;
+ }
+
+ AxWin_HandleMessage(msg);
+ free(msg);
+ }
+
+ return (tAxWin_Handle) ret->Handle;
+}
tAxWin_Message *AxWin_WaitForMessage();
int AxWin_HandleMessage(tAxWin_Message *Message);
+// === ===
+
// === CODE ===
+int AxWin_SendMessage(tAxWin_Message *Message)
+{
+ switch(giAxWin_Mode)
+ {
+ case AXWIN_MODE_IPC:
+ SysSendMessage(giAxWin_PID, Message->Size*4, Message);
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
/**
* \brief Loop forever, checking and waiting for messages
*/
{
struct sAxWin_Window *Next;
uint32_t WmHandle;
- tAxWin_MessageCallback Callback;
+ tAxWin_MessageCallback *Callback;
};
// === PROTOTYPES ===
-tAxWin_Handle AxWin_CreateWindow(
+tAxWin_Window *AxWin_CreateWindow(
int16_t X, int16_t Y, int16_t W, int16_t H,
uint32_t Flags, tAxWin_MessageCallback *Callback
);
tAxWin_Window *gProcessWindows;
// === CODE ===
-tAxWin_Handle AxWin_CreateWindow(
+tAxWin_Window *AxWin_CreateWindow(
int16_t X, int16_t Y,
int16_t W, int16_t H,
uint32_t Flags, tAxWin_MessageCallback *Callback)
CPPFLAGS += \r
CFLAGS += \r
ASFLAGS +=\r
-LDFLAGS += -soname libc.so.1 -Map map.txt -lgcc\r
+LDFLAGS += -soname libc.so -Map map.txt -lgcc\r
\r
OBJ = stub.o heap.o stdlib.o env.o fileIO.o string.o\r
DEPFILES := $(OBJ:%.o=%.d)\r
# signals.o\r
-BIN = ../libc.so.1\r
+BIN = ../libc.so\r
\r
.PHONY: all clean install\r
\r
all: $(BIN)\r
\r
clean:\r
- $(RM) $(BIN) ../libc.so $(OBJ) $(DEPFILES) libc.so.1.dsm libc.so.1.dmp map.txt\r
+ $(RM) $(BIN) $(OBJ) $(DEPFILES) libc.so.dsm libc.so.dmp map.txt\r
\r
install: $(BIN)\r
- $(xCP) ../libc.so.1 $(DISTROOT)/Libs/\r
+ $(xCP) $(BIN) $(DISTROOT)/Libs/\r
\r
# Core C Library\r
$(BIN): $(OBJ)\r
@$(LD) $(LDFLAGS) $(OBJ) -o $@\r
@$(OBJDUMP) -d $@ > libc.so.1.dsm\r
@$(OBJDUMP) -x -r -R $@ > libc.so.1.dmp\r
- cp ../libc.so.1 ../libc.so\r
\r
# C Runtime 0\r
../crt0.o: crt0.asm\r
#define _stdout 1\r
\r
// === PROTOTYPES ===\r
-EXPORT void itoa(char *buf, uint64_t num, int base, int minLength, char pad, int bSigned);\r
+EXPORT void itoa(char *buf, uint64_t num, uint base, int minLength, char pad, int bSigned);\r
struct sFILE *get_file_struct();\r
\r
// === GLOBALS ===\r
{\r
va_list tmpList = args;\r
int size;\r
- char *buf;\r
+ char sbuf[1024];\r
+ char *buf = sbuf;\r
\r
if(!fp || !format) return -1;\r
\r
- size = vsprintf(NULL, (char*)format, tmpList);\r
+ size = vsnprintf(sbuf, 1024, (char*)format, tmpList);\r
\r
- buf = (char*)malloc(size+1);\r
- buf[size] = '\0';\r
+ if( size >= 1024 )\r
+ {\r
+ buf = (char*)malloc(size+1);\r
+ if(!buf) {\r
+ write(_stdout, 31, "vfprintf ERROR: malloc() failed");\r
+ return 0;\r
+ }\r
+ buf[size] = '\0';\r
\r
- // Print\r
- vsprintf(buf, (char*)format, args);\r
+ // Print\r
+ vsnprintf(buf, size+1, (char*)format, args);\r
+ }\r
\r
// Write to stream\r
- write(fp->FD, size+1, buf);\r
+ write(fp->FD, size, buf);\r
\r
// Free buffer\r
free(buf);\r
return len;\r
}\r
\r
+EXPORT int vsprintf(char * __s, const char *__format, va_list __args)\r
+{\r
+ return vsnprintf(__s, 0x7FFFFFFF, __format, __args);\r
+}\r
+\r
//sprintfv\r
/**\r
- \fn EXPORT void vsprintf(char *buf, const char *format, va_list args)\r
+ \fn EXPORT void vsnprintf(char *buf, const char *format, va_list args)\r
\brief Prints a formatted string to a buffer\r
\param buf Pointer - Destination Buffer\r
\param format String - Format String\r
\param args VarArgs List - Arguments\r
*/\r
-EXPORT int vsprintf(char *buf, const char *format, va_list args)\r
+EXPORT int vsnprintf(char *buf, size_t __maxlen, const char *format, va_list args)\r
{\r
- char tmp[33];\r
+ char tmp[65];\r
int c, minSize;\r
int pos = 0;\r
char *p;\r
{\r
// Non-control character\r
if (c != '%') {\r
- if(buf) buf[pos] = c;\r
+ if(buf && pos < __maxlen) buf[pos] = c;\r
pos ++;\r
continue;\r
}\r
// Control Character\r
c = *format++;\r
if(c == '%') { // Literal %\r
- if(buf) buf[pos] = '%';\r
+ if(buf && pos < __maxlen) buf[pos] = '%';\r
pos ++;\r
continue;\r
}\r
\r
// Pointer\r
case 'p':\r
- if(buf) {\r
+ if(buf && pos+2 < __maxlen) {\r
buf[pos] = '*';\r
buf[pos+1] = '0';\r
buf[pos+2] = 'x';\r
}\r
pos += 3;\r
+ arg = va_arg(args, uint32_t);\r
+ itoa(tmp, arg, 16, minSize, pad, 0);\r
+ goto sprintf_puts;\r
// Fall through to hex\r
// Unsigned Hexadecimal\r
case 'x':\r
p = (void*)(intptr_t)arg;\r
sprintf_puts:\r
if(!p) p = "(null)";\r
+ //_SysDebug("vsnprintf: p = '%s'", p);\r
if(buf) {\r
while(*p) {\r
- buf[pos++] = *p++;\r
+ if(pos < __maxlen) buf[pos] = *p;\r
+ pos ++; p ++;\r
}\r
}\r
else {\r
// Unknown, just treat it as a character\r
default:\r
arg = va_arg(args, uint32_t);\r
- if(buf) buf[pos] = arg;\r
+ if(buf && pos < __maxlen) buf[pos] = arg;\r
pos ++;\r
break;\r
}\r
}\r
- if(buf) buf[pos] = '\0';\r
+ if(buf && pos < __maxlen) buf[pos] = '\0';\r
+ \r
+ //_SysDebug("vsnprintf: buf = '%s'", buf);\r
\r
return pos;\r
}\r
* \fn static void itoa(char *buf, uint64_t num, int base, int minLength, char pad, int bSigned)\r
* \brief Convert an integer into a character string\r
*/\r
-EXPORT void itoa(char *buf, uint64_t num, int base, int minLength, char pad, int bSigned)\r
+EXPORT void itoa(char *buf, uint64_t num, size_t base, int minLength, char pad, int bSigned)\r
{\r
- char tmpBuf[32];\r
+ char tmpBuf[64];\r
int pos=0, i;\r
\r
if(!buf) return;\r
- if(base > 16) {\r
+ if(base > 16 || base < 2) {\r
buf[0] = 0;\r
return;\r
}\r
bSigned = 0;\r
\r
while(num > base-1) {\r
- tmpBuf[pos] = cUCDIGITS[ num % base ];\r
- num = (long) num / base; // Shift {number} right 1 digit\r
- pos++;\r
+ tmpBuf[pos++] = cUCDIGITS[ num % base ];\r
+ num = (uint64_t) num / (uint64_t)base; // Shift {number} right 1 digit\r
}\r
\r
tmpBuf[pos++] = cUCDIGITS[ num % base ]; // Last digit of {number}\r
if(bSigned) tmpBuf[pos++] = '-'; // Append sign symbol if needed\r
+ \r
i = 0;\r
minLength -= pos;\r
while(minLength-- > 0) buf[i++] = pad;\r
{\r
#if 1\r
int size;\r
- char *buf;\r
+ char sbuf[1024];\r
+ char *buf = sbuf;\r
va_list args;\r
\r
// Get final size\r
va_start(args, format);\r
- size = vsprintf(NULL, (char*)format, args);\r
+ size = vsnprintf(sbuf, 1024, (char*)format, args);\r
va_end(args);\r
\r
- // Allocate buffer\r
- buf = (char*)malloc(size+1);\r
- buf[size] = '\0';\r
+ if( size >= 1024 ) {\r
+ // Allocate buffer\r
+ buf = (char*)malloc(size+1);\r
+ if(buf) {\r
+ write(_stdout, 29, "PRINTF ERROR: malloc() failed");\r
+ return 0;\r
+ }\r
+ buf[size] = '\0';\r
\r
- // Fill Buffer\r
- va_start(args, format);\r
- vsprintf(buf, (char*)format, args);\r
- va_end(args);\r
+ // Fill Buffer\r
+ va_start(args, format);\r
+ vsnprintf(buf, size+1, (char*)format, args);\r
+ va_end(args);\r
+ }\r
\r
// Send to stdout\r
write(_stdout, size+1, buf);\r
*/\r
#include <acess/sys.h>\r
#include <stdlib.h>\r
+#include <string.h>\r
#include "lib.h"\r
\r
// === Constants ===\r
\r
typedef unsigned int Uint;\r
\r
-//Typedefs\r
+// === TYPES ===\r
typedef struct {\r
Uint magic;\r
Uint size;\r
Uint magic;\r
} heap_foot;\r
\r
-//Globals\r
-void *_heap_start = NULL;\r
-void *_heap_end = NULL;\r
+// === LOCAL VARIABLES ===\r
+static void *_heap_start = NULL;\r
+static void *_heap_end = NULL;\r
\r
-//Prototypes\r
-EXPORT void *malloc(Uint bytes);\r
+// === PROTOTYPES ===\r
+EXPORT void *malloc(size_t bytes);\r
+EXPORT void *calloc(size_t bytes, size_t count);\r
EXPORT void free(void *mem);\r
EXPORT void *realloc(void *mem, Uint bytes);\r
EXPORT void *sbrk(int increment);\r
return (void*)(bestMatchAddr+sizeof(heap_head));\r
}\r
\r
+/**\r
+ * \fn EXPORT void *calloc(size_t bytes, size_t count)\r
+ * \brief Allocate and zero a block of memory\r
+ * \param __nmemb Number of memeber elements\r
+ * \param __size Size of one element\r
+ */\r
+EXPORT void *calloc(size_t __nmemb, size_t __size)\r
+{\r
+ void *ret = malloc(__size*__nmemb);\r
+ if(!ret) return NULL;\r
+ memset(ret, 0, __size*__nmemb);\r
+ return ret;\r
+}\r
+\r
/**\r
\fn EXPORT void free(void *mem)\r
\brief Free previously allocated memory\r
*/\r
#include "stdio_int.h"\r
#include "lib.h"\r
+#include <stdio.h>\r
+#include <sys/sys.h>\r
\r
#define USE_CPUID 0\r
\r
+// === TYPES ===\r
+typedef struct {\r
+ intptr_t Base;\r
+ char *Name;\r
+} tLoadedLib;\r
+\r
// === PROTOTYPES ===\r
#if USE_CPUID\r
static void cpuid(uint32_t Num, uint32_t *EAX, uint32_t *EBX, uint32_t *EDX, uint32_t *ECX);\r
#endif\r
+ int ErrorHandler(int Fault);\r
+\r
+// === IMPORTS ===\r
+extern tLoadedLib gLoadedLibraries[64];\r
\r
// === GLOBALS ===\r
extern char **_envp;\r
}\r
#endif\r
\r
+ // Set Error handler\r
+ _SysSetFaultHandler(ErrorHandler);\r
+ \r
return 1;\r
}\r
\r
+int ErrorHandler(int Fault)\r
+{\r
+ int i;\r
+ fprintf(stderr, "ErrorHandler: (Fault = %i)\n", Fault);\r
+ fprintf(stderr, "Loaded Libraries:\n");\r
+ for( i = 0; i < 64; i ++ )\r
+ {\r
+ //if(gLoadedLibraries[i].Base == 0) continue;\r
+ // fprintf(stderr, "%02i: %p %s\n", i, gLoadedLibraries[i].Base, gLoadedLibraries[i].Name);\r
+ }\r
+ fprintf(stderr, "\n");\r
+ return -1;\r
+}\r
\r
#if USE_CPUID\r
/**\r
*/
uint64_t __udivdi3(uint64_t Num, uint64_t Den)
{
+ #if 0
uint64_t ret = 0;
if(Den == 0) // Call Div by Zero Error
__asm__ __volatile__ ("int $0");
+
+ if(Den == 1) return Num;
+ if(Den == 2) return Num >> 1;
+ if(Den == 4) return Num >> 2;
+ if(Den == 8) return Num >> 3;
+ if(Den == 16) return Num >> 4;
+ if(Den == 32) return Num >> 5;
+ if(Den == 64) return Num >> 6;
+ if(Den == 128) return Num >> 7;
+ if(Den == 256) return Num >> 8;
+
while(Num > Den) {
ret ++;
Num -= Den;
}
return ret;
+ #else
+ uint64_t P[64], q, n;
+ int i;
+
+ if(Den == 0) __asm__ __volatile__ ("int $0x0");
+ // Common speedups
+ if(Den == 1) return Num;
+ if(Den == 2) return Num >> 1;
+ if(Den == 16) return Num >> 4;
+
+
+ // Non-restoring division, from wikipedia
+ // http://en.wikipedia.org/wiki/Division_(digital)
+ P[0] = Num;
+ for( i = 0; i < 64; i ++ )
+ {
+ if( P[i] >= 0 ) {
+ q |= (uint64_t)1 << (63-i);
+ P[i+1] = 2*P[i] - Den;
+ }
+ else {
+ //q |= 0 << (63-i);
+ P[i+1] = 2*P[i] + Den;
+ }
+ }
+
+ n = ~q;
+ n = -n;
+ q += n;
+
+ return q;
+ #endif
}
/**
*/
uint64_t __umoddi3(uint64_t Num, uint64_t Den)
{
- if(Den == 0) // Call Div by Zero Error
- __asm__ __volatile__ ("int $0");
- while(Num >= Den)
- Num -= Den;
+ #if 0
+ if(Den == 0) __asm__ __volatile__ ("int $0"); // Call Div by Zero Error
+
+ if(Den == 1) return 0;
+ if(Den == 2) return Num & 0x01;
+ if(Den == 4) return Num & 0x03;
+ if(Den == 8) return Num & 0x07;
+ if(Den == 16) return Num & 0x0F;
+ if(Den == 32) return Num & 0x1F;
+ if(Den == 64) return Num & 0x3F;
+ if(Den == 128) return Num & 0x3F;
+ if(Den == 256) return Num & 0x7F;
+
+ while(Num >= Den) Num -= Den;
+
return Num;
+ #else
+ if(Den == 0) __asm__ __volatile__ ("int $0"); // Call Div by Zero Error
+ // Speedups for common operations
+ if(Den == 1) return 0;
+ if(Den == 2) return Num & 0x01;
+ if(Den == 16) return Num & 0x0F;
+ return Num - __udivdi3(Num, Den) * Den;
+ #endif
}
/*
* Acess2 System Interface Header
*/
-#ifndef _SYS_SYS_H_
-#define _SYS_SYS_H_
+#ifndef _ACESS_SYS_H_
+#define _ACESS_SYS_H_
#include <stdint.h>
+#include <sys/types.h>
// === CONSTANTS ===
#ifndef NULL
#define FILEFLAG_SYMLINK 0x20
// === TYPES ===
-typedef uint pid_t;
-
struct s_sysACL {
union {
struct {
extern int _errno;
// === FUNCTIONS ===
-extern void _SysDebug(char *str, ...);
+extern void _SysDebug(const char *format, ...);
// --- Proc ---
extern void _exit(int status) __attribute__((noreturn));
extern void sleep();
extern int execve(char *path, char **argv, char **envp);
extern int gettid();
extern int getpid();
+extern int _SysSetFaultHandler(int (*Handler)(int));
// --- Permissions ---
extern int getuid();
extern void close(int fd);
extern uint read(int fd, uint length, void *buffer);
extern uint write(int fd, uint length, void *buffer);
-extern int seek(int fd, uint64_t offset, int whence);
+extern int seek(int fd, int64_t offset, int whence);
extern uint64_t tell(int fd);
extern int ioctl(int fd, int id, void *data);
extern int finfo(int fd, t_sysFInfo *info, int maxacls);
extern int readdir(int fd, char *dest);
+extern int _SysOpenChild(int fd, char *name, int flags);
extern int _SysGetACL(int fd, t_sysACL *dest);
extern int _SysMount(const char *Device, const char *Directory, const char *Type, const char *Options);
#define _AXWIN_AXWIN_H
// === Core Types ===
-typedef unsigned int tAxWin_Handle;
+typedef void *tAxWin_Handle;
// === Messaging ===
#include "messages.h"
extern int AxWin_MessageLoop();
+extern int AxWin_SendMessage(tAxWin_Message *Message);
+extern tAxWin_Message *AxWin_WaitForMessage(void);
+extern int AxWin_HandleMessage(tAxWin_Message *Message);
// === Window Control ===
/**
/**
* \}
*/
-extern tAxWin_Window AxWin_CreateWindow(
+extern tAxWin_Window *AxWin_CreateWindow(
int16_t X, int16_t Y, int16_t W, int16_t H,
uint32_t Flags, tAxWin_MessageCallback *Callback);
#include <stdint.h>
typedef struct sAxWin_Message tAxWin_Message;
+typedef struct sAxWin_RetMsg tAxWin_RetMsg;
+
+// Higherarchy:
+// - HANDLE
+// + ELEMENT
+// > DIALOG
+// > TAB
/**
* \brief Message IDs
// - Windows
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_ADDTAB, // TAB (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_NEWDIALOG, // DIALOG (TAB Parent, char[] Name) - Creates a dialog
+ MSG_SREQ_DELDIALOG, // void (DIALOG Dialog) - Closes a dialog
MSG_SREQ_SETNAME, // void (ELEMENT Element, char[] Name)
MSG_SREQ_GETNAME, // char[] (ELEMENT Element)
MSG_SREQ_SETFONT, MSG_SREQ_PUTTEXT,
// Server Responses
+ MSG_SRSP_VERSION,
MSG_SRSP_RETURN, // {int RequestID, void[] Return Value} - Returns a value from a server request
NUM_MSG
* \brief Server Response - Pong
* \see eAxWin_Messages.MSG_SRSP_PONG
*/
-struct sAxWin_SRsp_Pong
+struct sAxWin_SRsp_Version
{
uint8_t Major;
uint8_t Minor;
{
uint16_t ID;
uint16_t Size; //!< Size in DWORDS
+ char Data[];
+};
+
+struct sAxWin_RetMsg
+{
+ uint16_t ReqID;
+ uint16_t Rsvd;
union
{
- struct sAxWin_SReq_Ping SReq_Pong;
- struct sAxWin_SReq_NewWindow SReq_NewWindow;
-
- // Server Responses
- struct sAxWin_SRsp_Pong SRsp_Pong;
- struct sAxWin_SRsp_NewWindow SRsp_Window;
+ uint8_t Bool;
+ uint32_t Handle;
+ int Integer;
};
};
\r
// --- Standard IO ---\r
extern int printf(const char *format, ...);\r
+extern int vsnprintf(char *buf, size_t __maxlen, const char *format, va_list args);\r
extern int vsprintf(char *buf, const char *format, va_list args);\r
extern int sprintf(char *buf, const char *format, ...);\r
\r
#define UNLOCK(_name) __asm__ __volatile__("lock andl $0, (%0)"::"D"(&_spinlock_##_name))\r
\r
// --- StdLib ---\r
-extern void _exit(int code); //NOTE: Also defined in acess/sys.h\r
+extern void _exit(int code) __attribute__((noreturn)); //NOTE: Also defined in acess/sys.h\r
extern int atoi(const char *ptr);\r
extern void exit(int status) __attribute__((noreturn));\r
extern void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *));\r
\r
// --- Heap ---\r
extern void free(void *mem);\r
-extern void *malloc(unsigned int bytes);\r
-extern void *realloc(void *oldPos, unsigned int bytes);\r
+extern void *malloc(size_t bytes);\r
+extern void *calloc(size_t __nmemb, size_t __size);\r
+extern void *realloc(void *__ptr, size_t __size);\r
extern int IsHeap(void *ptr);\r
\r
#ifndef SEEK_CUR\r
+++ /dev/null
-/*
- * AcessOS LibC
- * string.h
- */
-#ifndef __STRING_H
-#define __STRING_H
-
-#include <stddef.h>
-
-// Strings
-extern int strlen(const char *string);
-extern int strcmp(const char *str1, const char *str2);
-extern int strncmp(const char *str1, const char *str2, size_t len);
-extern char *strcpy(char *dst, const char *src);
-extern char *strncpy(char *dst, const char *src, size_t num);
-extern char *strcat(char *dst, const char *src);
-extern char *strdup(const char *src);
-extern char *strchr(char *str, int character);
-extern char *strrchr(char *str, int character);
-extern char *strstr(char *str1, const char *str2);
-
-// Memory
-extern void *memset(void *dest, int val, size_t count);
-extern void *memcpy(void *dest, const void *src, size_t count);
-extern void *memmove(void *dest, const void *src, size_t count);
-extern int memcmp(const void *mem1, const void *mem2, size_t count);
-extern void *memchr(void *ptr, int value, size_t num);
-
-#endif
--- /dev/null
+/*
+ * AcessOS LibC
+ * string.h
+ */
+#ifndef __STRING_H
+#define __STRING_H
+
+#include <stddef.h>
+
+// Strings
+extern int strlen(const char *string);
+extern int strcmp(const char *str1, const char *str2);
+extern int strncmp(const char *str1, const char *str2, size_t len);
+extern char *strcpy(char *dst, const char *src);
+extern char *strncpy(char *dst, const char *src, size_t num);
+extern char *strcat(char *dst, const char *src);
+extern char *strdup(const char *src);
+extern char *strchr(char *str, int character);
+extern char *strrchr(char *str, int character);
+extern char *strstr(char *str1, const char *str2);
+
+// Memory
+extern void *memset(void *dest, int val, size_t count);
+extern void *memcpy(void *dest, const void *src, size_t count);
+extern void *memmove(void *dest, const void *src, size_t count);
+extern int memcmp(const void *mem1, const void *mem2, size_t count);
+extern void *memchr(void *ptr, int value, size_t num);
+
+#endif
/*\r
Syscall Definitions\r
*/\r
+#ifndef _SYS_SYS_H_\r
+#define _SYS_SYS_H_\r
\r
#include <sys/types.h>\r
\r
extern int read(int fp, int len, void *buf);\r
extern int write(int fp, int len, void *buf);\r
extern int tell(int fp);\r
-extern void seek(int fp, int dist, int flag);\r
+extern void seek(int fp, int64_t dist, int flag);\r
extern int fstat(int fp, t_fstat *st);\r
extern int ioctl(int fp, int call, void *arg);\r
extern int readdir(int fp, char *file);\r
extern int sendmsg(int dest, unsigned int *Data);\r
extern int pollmsg(int *src, unsigned int *Data);\r
extern int getmsg(int *src, unsigned int *Data);\r
+\r
+#endif\r
-
+/*
+ */
#ifndef _SYS_TYPES_H
#define _SYS_TYPES_H
+#include <stdint.h>
typedef struct {
int st_dev; //dev_t
#define S_IFSOCK 0140000 /* socket */
#define S_IFIFO 0010000 /* fifo */
+
+typedef uint32_t pid_t;
+typedef uint32_t tid_t;
+typedef int64_t time_t;
+
#endif