From 049de1f2533477716a12a708c097b199eaa8fb6c Mon Sep 17 00:00:00 2001 From: John Hodge Date: Fri, 2 Apr 2010 15:48:24 +0800 Subject: [PATCH] VM8086 Support, Starting on VESA Driver - VM8086 required some changes to CPU fault code - Re-enabled kernel magic combos in keyboard driver - Slight changes to Memory APIs (changed MM_MapHWPage to MM_MapHWPages) --- Kernel/Makefile.BuildNum | 2 +- Kernel/arch/x86/Makefile | 2 +- Kernel/arch/x86/errors.c | 11 ++ Kernel/arch/x86/include/vm8086.h | 44 ++++- Kernel/arch/x86/mm_phys.c | 32 ++- Kernel/arch/x86/mm_virt.c | 16 +- Kernel/arch/x86/proc.c | 27 ++- Kernel/arch/x86/vm8086.c | 329 +++++++++++++++++++++++++++++++ Kernel/binary.c | 1 - Kernel/drv/kb.c | 12 +- Kernel/include/acess.h | 6 +- Kernel/include/threads.h | 2 +- Kernel/threads.c | 29 ++- Makefile | 50 ++--- Makefile.cfg | 3 +- Modules/Display/VESA/Makefile | 7 + Modules/Display/VESA/common.h | 59 ++++++ Modules/Display/VESA/main.c | 286 +++++++++++++++++++++++++++ Modules/Makefile.tpl | 2 +- Modules/Network/Makefile.tpl | 2 + Modules/Storage/ATA/main.c | 2 +- Modules/USB/Core/Makefile | 2 +- 22 files changed, 859 insertions(+), 67 deletions(-) create mode 100644 Kernel/arch/x86/vm8086.c create mode 100644 Modules/Display/VESA/Makefile create mode 100644 Modules/Display/VESA/common.h create mode 100644 Modules/Display/VESA/main.c diff --git a/Kernel/Makefile.BuildNum b/Kernel/Makefile.BuildNum index dc7f7ff2..a5712863 100644 --- a/Kernel/Makefile.BuildNum +++ b/Kernel/Makefile.BuildNum @@ -1 +1 @@ -BUILD_NUM = 1636 +BUILD_NUM = 1696 diff --git a/Kernel/arch/x86/Makefile b/Kernel/arch/x86/Makefile index 87dd2b23..708c8dc1 100644 --- a/Kernel/arch/x86/Makefile +++ b/Kernel/arch/x86/Makefile @@ -31,5 +31,5 @@ endif A_OBJ = start.ao main.o lib.o desctab.ao errors.o irq.o A_OBJ += mm_phys.o mm_virt.o -A_OBJ += proc.o time.o +A_OBJ += proc.o time.o vm8086.o #A_OBJ += gdb_stub.o diff --git a/Kernel/arch/x86/errors.c b/Kernel/arch/x86/errors.c index cfc70753..b53807aa 100644 --- a/Kernel/arch/x86/errors.c +++ b/Kernel/arch/x86/errors.c @@ -11,6 +11,7 @@ // === IMPORTS === extern void MM_PageFault(Uint Addr, Uint ErrorCode, tRegs *Regs); +extern void VM8086_GPF(tRegs *Regs); extern void Threads_Dump(); // === PROTOTYPES === @@ -44,6 +45,9 @@ void ErrorHandler(tRegs *Regs) Uint cr; __asm__ __volatile__ ("cli"); + //Log_Debug("X86", "Error %i at 0x%08x", Regs->int_num, Regs->eip); + + // Page Fault if(Regs->int_num == 14) { __asm__ __volatile__ ("mov %%cr2, %0":"=r"(cr)); @@ -51,6 +55,13 @@ void ErrorHandler(tRegs *Regs) return ; } + // VM8086 GPF + if(Regs->int_num == 13 && Regs->eflags & 0x20000) + { + VM8086_GPF(Regs); + return ; + } + Warning("CPU Error %i - %s, Code: 0x%x", Regs->int_num, csaERROR_NAMES[Regs->int_num], Regs->err_code); Warning(" CS:EIP = 0x%04x:%08x", Regs->cs, Regs->eip); diff --git a/Kernel/arch/x86/include/vm8086.h b/Kernel/arch/x86/include/vm8086.h index cb2834c2..353ad7a3 100644 --- a/Kernel/arch/x86/include/vm8086.h +++ b/Kernel/arch/x86/include/vm8086.h @@ -9,21 +9,59 @@ #define _VM80806_H_ // === TYPES === +/** + * \note Semi-opaque - Past \a .IP, the implementation may add any data + * it needs to the state. + */ typedef struct sVM8086 { Uint16 AX, CX, DX, BX; Uint16 BP, SP, SI, DI; - Uint16 CS, SS, DS, ES; + Uint16 SS, DS, ES; + + Uint16 CS, IP; - Uint16 IP; + struct sVM8086_InternalData *Internal; } tVM8086; // === FUNCTIONS === +/** + * \brief Create an instance of the VM8086 Emulator + * \note Do not free this pointer with ::free, instead use ::VM8086_Free + * \return Pointer to a tVM8086 structure, this structure may be larger than + * tVM8086 due to internal data. + */ extern tVM8086 *VM8086_Init(void); +/** + * \brief Free an allocated tVM8086 structure + * \param State Emulator state to free + */ extern void VM8086_Free(tVM8086 *State); -extern void *VM8086_Allocate(tVM8086 *State, int Size, Uint16 *Segment, Uint16 *Ofs); +/** + * \brief Allocate a piece of memory in the emulated address space and + * return a host and emulated pointer to it. + * \param State Emulator state + * \param Size Size of memory block + * \param Segment Pointer to location to store the allocated memory's segment + * \param Offset Pointet to location to store the allocated memory's offset + * \return Host pointer to the allocated memory + */ +extern void *VM8086_Allocate(tVM8086 *State, int Size, Uint16 *Segment, Uint16 *Offset); +/** + * \brief Gets a pointer to a piece of emulated memory + * \todo Only 1 machine page is garenteed to be contiguous + * \param State Emulator State + * \param Segment Source Segment + * \param Offset Source Offset + * \return Host pointer to the emulated memory + */ extern void *VM8086_GetPointer(tVM8086 *State, Uint16 Segment, Uint16 Ofs); +/** + * \brief Calls a real-mode interrupt described by the current state of the IVT. + * \param State Emulator State + * \param Interrupt BIOS Interrupt to call + */ extern void VM8086_Int(tVM8086 *State, Uint8 Interrupt); #endif diff --git a/Kernel/arch/x86/mm_phys.c b/Kernel/arch/x86/mm_phys.c index 988a15e4..f091c63a 100644 --- a/Kernel/arch/x86/mm_phys.c +++ b/Kernel/arch/x86/mm_phys.c @@ -73,7 +73,7 @@ void MM_Install(tMBoot_Info *MBoot) ent = (tMBoot_MMapEnt *)( (Uint)ent + ent->Size ); } - // Get used page count + // Get used page count (Kernel) kernelPages = (Uint)&gKernelEnd - KERNEL_BASE - 0x100000; kernelPages += 0xFFF; // Page Align kernelPages >>= 12; @@ -211,8 +211,13 @@ tPAddr MM_AllocPhysRange(int Pages, int MaxBits) int i, idx, sidx; tPAddr ret; + ENTER("iPages iMaxBits", Pages, MaxBits); + // Sanity Checks - if(MaxBits < 0) return 0; + if(MaxBits < 0) { + LEAVE('i', 0); + return 0; + } if(MaxBits > PHYS_BITS) MaxBits = PHYS_BITS; // Lock @@ -230,16 +235,28 @@ tPAddr MM_AllocPhysRange(int Pages, int MaxBits) b = idx % 32; a = idx / 32; + #if 0 + LOG("a=%i, b=%i, idx=%i, sidx=%i", a, b, idx, sidx); + // Find free page - for( ; gaSuperBitmap[a] == -1 && a --; ); + for( ; gaSuperBitmap[a] == -1 && a --; ) b = 31; if(a < 0) { RELEASE( &giPhysAlloc ); Warning("MM_AllocPhysRange - OUT OF MEMORY (Called by %p)", __builtin_return_address(0)); + LEAVE('i', 0); return 0; } - for( ; gaSuperBitmap[a] & (1 << b); b-- ); + LOG("a = %i", a); + for( ; gaSuperBitmap[a] & (1 << b); b-- ) sidx = 31; + LOG("b = %i", b); idx = a * 32 + b; - for( ; gaPageBitmap[idx] & (1 << sidx); sidx-- ); + for( ; gaPageBitmap[idx] & (1 << sidx); sidx-- ) + LOG("gaPageBitmap[%i] = 0x%08x", idx, gaPageBitmap[idx]); + + LOG("idx = %i, sidx = %i", idx, sidx); + #else + + #endif // Check if the gap is large enough while( idx >= 0 ) @@ -284,6 +301,8 @@ tPAddr MM_AllocPhysRange(int Pages, int MaxBits) if( idx < 0 ) { RELEASE( &giPhysAlloc ); Warning("MM_AllocPhysRange - OUT OF MEMORY (Called by %p)", __builtin_return_address(0)); + LEAVE('i', 0); + return 0; } // Mark pages used @@ -293,7 +312,7 @@ tPAddr MM_AllocPhysRange(int Pages, int MaxBits) gaPageReferences[idx*32+sidx] = 1; gaPageBitmap[ idx ] |= 1 << sidx; sidx ++; - if(sidx == 32) { sidx = 0; idx ++; } + if(sidx == 32) { sidx = 0; idx ++; } } // Get address @@ -305,6 +324,7 @@ tPAddr MM_AllocPhysRange(int Pages, int MaxBits) // Release Spinlock RELEASE( &giPhysAlloc ); + LEAVE('X', ret); return ret; } diff --git a/Kernel/arch/x86/mm_virt.c b/Kernel/arch/x86/mm_virt.c index 958b9f15..6976c657 100644 --- a/Kernel/arch/x86/mm_virt.c +++ b/Kernel/arch/x86/mm_virt.c @@ -895,10 +895,10 @@ void MM_FreeTemp(tVAddr VAddr) } /** - * \fn tVAddr MM_MapHWPage(tPAddr PAddr, Uint Number) + * \fn tVAddr MM_MapHWPages(tPAddr PAddr, Uint Number) * \brief Allocates a contigous number of pages */ -tVAddr MM_MapHWPage(tPAddr PAddr, Uint Number) +tVAddr MM_MapHWPages(tPAddr PAddr, Uint Number) { int i, j; @@ -962,7 +962,7 @@ tVAddr MM_AllocDMA(int Pages, int MaxBits, tPAddr *PhysAddr) { phys = MM_AllocPhys(); *PhysAddr = phys; - ret = MM_MapHWPage(phys, 1); + ret = MM_MapHWPages(phys, 1); if(ret == 0) { MM_DerefPhys(phys); LEAVE('i', 0); @@ -981,7 +981,7 @@ tVAddr MM_AllocDMA(int Pages, int MaxBits, tPAddr *PhysAddr) } // Allocated successfully, now map - ret = MM_MapHWPage(phys, Pages); + ret = MM_MapHWPages(phys, Pages); if( ret == 0 ) { // If it didn't map, free then return 0 for(;Pages--;phys+=0x1000) @@ -996,10 +996,10 @@ tVAddr MM_AllocDMA(int Pages, int MaxBits, tPAddr *PhysAddr) } /** - * \fn void MM_UnmapHWPage(tVAddr VAddr, Uint Number) + * \fn void MM_UnmapHWPages(tVAddr VAddr, Uint Number) * \brief Unmap a hardware page */ -void MM_UnmapHWPage(tVAddr VAddr, Uint Number) +void MM_UnmapHWPages(tVAddr VAddr, Uint Number) { int i, j; // Sanity Check @@ -1022,6 +1022,6 @@ void MM_UnmapHWPage(tVAddr VAddr, Uint Number) EXPORT(MM_GetPhysAddr); EXPORT(MM_Map); //EXPORT(MM_Unmap); -EXPORT(MM_MapHWPage); +EXPORT(MM_MapHWPages); EXPORT(MM_AllocDMA); -EXPORT(MM_UnmapHWPage); +EXPORT(MM_UnmapHWPages); diff --git a/Kernel/arch/x86/proc.c b/Kernel/arch/x86/proc.c index a66a540c..b2f7f8f5 100644 --- a/Kernel/arch/x86/proc.c +++ b/Kernel/arch/x86/proc.c @@ -15,6 +15,7 @@ // === CONSTANTS === #define SWITCH_MAGIC 0xFFFACE55 // There is no code in this area +// Base is 1193182 #define TIMER_DIVISOR 11931 //~100Hz // === IMPORTS === @@ -47,6 +48,7 @@ void Proc_Start(); tThread *Proc_GetCurThread(); void Proc_ChangeStack(); int Proc_Clone(Uint *Err, Uint Flags); +void Proc_StartProcess(Uint16 SS, Uint Stack, Uint Flags, Uint16 CS, Uint IP); void Proc_Scheduler(); // === GLOBALS === @@ -601,13 +603,18 @@ void Proc_StartUser(Uint Entrypoint, Uint *Bases, int ArgC, char **ArgV, char ** while(*Bases) *--stack = *Bases++; *--stack = 0; // Return Address - delta = (Uint)stack; // Reuse delta to save SP - *--stack = ss; //Stack Segment - *--stack = delta; //Stack Pointer - *--stack = 0x0202; //EFLAGS (Resvd (0x2) and IF (0x20)) - *--stack = cs; //Code Segment - *--stack = Entrypoint; //EIP + Proc_StartProcess(ss, (Uint)stack, 0x202, cs, Entrypoint); +} + +void Proc_StartProcess(Uint16 SS, Uint Stack, Uint Flags, Uint16 CS, Uint IP) +{ + Uint *stack = (void*)Stack; + *--stack = SS; //Stack Segment + *--stack = Stack; //Stack Pointer + *--stack = Flags; //EFLAGS (Resvd (0x2) and IF (0x20)) + *--stack = CS; //Code Segment + *--stack = IP; //EIP //PUSHAD *--stack = 0xAAAAAAAA; // eax *--stack = 0xCCCCCCCC; // ecx @@ -618,10 +625,10 @@ void Proc_StartUser(Uint Entrypoint, Uint *Bases, int ArgC, char **ArgV, char ** *--stack = 0x51515151; // esi *--stack = 0xB4B4B4B4; // ebp //Individual PUSHs - *--stack = ss; // ds - *--stack = ss; // es - *--stack = ss; // fs - *--stack = ss; // gs + *--stack = SS; // ds + *--stack = SS; // es + *--stack = SS; // fs + *--stack = SS; // gs __asm__ __volatile__ ( "mov %%eax,%%esp;\n\t" // Set stack pointer diff --git a/Kernel/arch/x86/vm8086.c b/Kernel/arch/x86/vm8086.c new file mode 100644 index 00000000..abc08dce --- /dev/null +++ b/Kernel/arch/x86/vm8086.c @@ -0,0 +1,329 @@ +/* + * Acess2 VM8086 Driver + * - By John Hodge (thePowersGang) + */ +#include +#include +#include + +// === CONSTANTS === +#define VM8086_MAGIC_CS 0xFFFF +#define VM8086_MAGIC_IP 0x0010 +#define VM8086_STACK_SEG 0x9F00 +#define VM8086_STACK_OFS 0x0AFE +enum eVM8086_Opcodes +{ + VM8086_OP_PUSHF = 0x9C, + VM8086_OP_POPF = 0x9D, + VM8086_OP_INT_I = 0xCD, + VM8086_OP_IRET = 0xCF +}; +#define VM8086_PAGES_PER_INST 4 + +// === IMPORTS === + int Proc_Clone(Uint *Err, Uint Flags); + +// === TYPES === +struct sVM8086_InternalData +{ + struct { + Uint32 Bitmap; // 32 sections = 128 byte blocks + tVAddr VirtBase; + tPAddr PhysAddr; + } AllocatedPages[VM8086_PAGES_PER_INST]; +}; + +// === PROTOTYPES === + int VM8086_Install(char **Arguments); +void VM8086_GPF(tRegs *Regs); +tVM8086 *VM8086_Init(void); + +// === GLOBALS === +MODULE_DEFINE(0, 0x100, VM8086, VM8086_Install, NULL, NULL); +tSpinlock glVM8086_Process; +tPID gVM8086_WorkerPID; +tTID gVM8086_CallingThread; +tVM8086 * volatile gpVM8086_State; + +// === FUNCTIONS === +int VM8086_Install(char **Arguments) +{ + tPID pid; + + // Create BIOS Call process + pid = Proc_Clone(NULL, CLONE_VM); + if(pid == -1) + { + Log_Error("VM8086", "Unable to clone kernel into VM8086 worker"); + return MODULE_ERR_MISC; + } + if(pid == 0) + { + Uint *stacksetup; // Initialising Stack + Uint16 *rmstack; // Real Mode Stack + int i; + + // Set Image Name + Threads_SetName("VM8086"); + + // Map ROM Area + for(i=0xA0;i<0x100;i++) { + MM_Map( i * 0x1000, i * 0x1000 ); + MM_SetFlags( i * 0x1000, MM_PFLAG_RO, MM_PFLAG_RO ); // Set Read Only + } + MM_Map( 0, 0 ); // IVT / BDA + for(i=0x70;i<0x80;i++) { + MM_Map( i * 0x1000, i * 0x1000 ); MM_DerefPhys( i * 0x1000 ); + } + MM_Map( 0x9F000, 0x9F000 ); // Stack / EBDA + MM_Allocate( 0x100000 ); // System Stack / Stub + + *(Uint8*)(0x100000) = VM8086_OP_IRET; + *(Uint8*)(0x100001) = 0x07; // POP ES + *(Uint8*)(0x100002) = 0x1F; // POP DS + *(Uint8*)(0x100003) = 0xCB; // RET FAR + + rmstack = (Uint16*)(VM8086_STACK_SEG*16 + VM8086_STACK_OFS); + *rmstack-- = 0xFFFF; //CS + *rmstack-- = 0x0010; //IP + + // Setup Stack + stacksetup = (Uint*)0x101000; + *--stacksetup = VM8086_STACK_SEG; // GS + *--stacksetup = VM8086_STACK_SEG; // FS + *--stacksetup = VM8086_STACK_SEG; // DS + *--stacksetup = VM8086_STACK_SEG; // ES + *--stacksetup = VM8086_STACK_SEG; // SS + *--stacksetup = VM8086_STACK_OFS-2; // SP + *--stacksetup = 0x20202; // FLAGS + *--stacksetup = 0xFFFF; // CS + *--stacksetup = 0x10; // IP + *--stacksetup = 0xAAAA; // AX + *--stacksetup = 0xCCCC; // CX + *--stacksetup = 0xDDDD; // DX + *--stacksetup = 0xBBBB; // BX + *--stacksetup = 0x5454; // SP + *--stacksetup = 0xB4B4; // BP + *--stacksetup = 0x5151; // SI + *--stacksetup = 0xD1D1; // DI + *--stacksetup = 0x20|3; // DS - Kernel + *--stacksetup = 0x20|3; // ES - Kernel + *--stacksetup = 0x20|3; // FS + *--stacksetup = 0x20|3; // GS + __asm__ __volatile__ ( + "mov %%eax,%%esp;\n\t" // Set stack pointer + "pop %%gs;\n\t" + "pop %%fs;\n\t" + "pop %%es;\n\t" + "pop %%ds;\n\t" + "popa;\n\t" + "iret;\n\t" : : "a" (stacksetup)); + for(;;); // Shouldn't be reached + } + + gVM8086_WorkerPID = pid; + Log_Log("VM8086", "gVM8086_WorkerPID = %i", pid); + Threads_Yield(); // Yield to allow the child to initialise + + return MODULE_ERR_OK; +} + +void VM8086_GPF(tRegs *Regs) +{ + Uint8 opcode; + + //Log_Log("VM8086", "GPF - %04x:%04x", Regs->cs, Regs->eip); + + if(Regs->eip == VM8086_MAGIC_IP && Regs->cs == VM8086_MAGIC_CS + && Threads_GetPID() == gVM8086_WorkerPID) + { + if( gpVM8086_State ) { + gpVM8086_State->AX = Regs->eax; gpVM8086_State->CX = Regs->ecx; + gpVM8086_State->DX = Regs->edx; gpVM8086_State->BX = Regs->ebx; + gpVM8086_State->BP = Regs->ebp; + gpVM8086_State->SI = Regs->esi; gpVM8086_State->DI = Regs->edi; + gpVM8086_State->DS = Regs->ds; gpVM8086_State->ES = Regs->es; + gpVM8086_State = NULL; + Threads_WakeTID(gVM8086_CallingThread); + } + + //Log_Log("VM8086", "Waiting for something to do"); + __asm__ __volatile__ ("sti"); + // Wait for a new task + while(!gpVM8086_State) { + Threads_Sleep(); + //Log_Log("VM8086", "gpVM8086_State = %p", gpVM8086_State); + } + + //Log_Log("VM8086", "We have a task"); + Regs->esp -= 2; *(Uint16*)( (Regs->ss<<4) + (Regs->esp&0xFFFF) ) = VM8086_MAGIC_CS; + Regs->esp -= 2; *(Uint16*)( (Regs->ss<<4) + (Regs->esp&0xFFFF) ) = VM8086_MAGIC_IP; + Regs->esp -= 2; *(Uint16*)( (Regs->ss<<4) + (Regs->esp&0xFFFF) ) = gpVM8086_State->CS; + Regs->esp -= 2; *(Uint16*)( (Regs->ss<<4) + (Regs->esp&0xFFFF) ) = gpVM8086_State->IP; + Regs->esp -= 2; *(Uint16*)( (Regs->ss<<4) + (Regs->esp&0xFFFF) ) = gpVM8086_State->DS; + Regs->esp -= 2; *(Uint16*)( (Regs->ss<<4) + (Regs->esp&0xFFFF) ) = gpVM8086_State->ES; + + // Set Registers + Regs->eip = 0x11; Regs->cs = 0xFFFF; + Regs->eax = gpVM8086_State->AX; Regs->ecx = gpVM8086_State->CX; + Regs->edx = gpVM8086_State->DX; Regs->ebx = gpVM8086_State->BX; + Regs->esi = gpVM8086_State->SI; Regs->edi = gpVM8086_State->DI; + Regs->ebp = gpVM8086_State->BP; + Regs->ds = 0x23; Regs->es = 0x23; + Regs->fs = 0x23; Regs->gs = 0x23; + return ; + } + + opcode = *(Uint8*)( KERNEL_BASE + (Regs->cs*16) + (Regs->eip) ); + Regs->eip ++; + switch(opcode) + { + case VM8086_OP_PUSHF: //PUSHF + Regs->esp -= 2; + *(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) ) = Regs->eflags & 0xFFFF; + #if TRACE_EMU + Log_Debug("VM8086", "Emulated PUSHF"); + #endif + break; + case VM8086_OP_POPF: //POPF + Regs->eflags &= 0xFFFF0002; + Regs->eflags |= *(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) ) & 0xFFFD; // Changing IF is not allowed + Regs->esp += 2; + #if TRACE_EMU + Log_Debug("VM8086", "Emulated POPF"); + #endif + break; + + case VM8086_OP_INT_I: //INT imm8 + { + int id; + id = *(Uint8*)( Regs->cs*16 +(Regs->eip&0xFFFF)); + Regs->eip ++; + + Regs->esp -= 2; *(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) ) = Regs->cs; + Regs->esp -= 2; *(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) ) = Regs->eip; + + Regs->cs = *(Uint16*)(4*id + 2); + Regs->eip = *(Uint16*)(4*id); + #if TRACE_EMU + Log_Debug("VM8086", "Emulated INT 0x%x", id); + #endif + } + break; + + case 0xCF: //IRET + Regs->eip = *(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) ); Regs->esp += 2; + Regs->cs = *(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) ); Regs->esp += 2; + #if TRACE_EMU + Log_Debug("VM8086", "IRET to %04x:%04x", Regs->cs, Regs->eip); + #endif + break; + + default: + Log_Error("VM8086", "Error - Unknown opcode %02x caused a GPF at %04x:%04x", + opcode, Regs->cs, Regs->eip); + // Force an end to the call + Regs->cs = VM8086_MAGIC_CS; + Regs->eip = VM8086_MAGIC_IP; + break; + } +} + +/** + * \brief Create an instance of the VM8086 Emulator + */ +tVM8086 *VM8086_Init(void) +{ + tVM8086 *ret; + ret = calloc( 1, sizeof(tVM8086) + sizeof(struct sVM8086_InternalData) ); + ret->Internal = (void*)((tVAddr)ret + sizeof(tVM8086)); + return ret; +} + +void VM8086_Free(tVM8086 *State) +{ + int i; + for( i = VM8086_PAGES_PER_INST; i --; ) + MM_UnmapHWPages( State->Internal->AllocatedPages[i].VirtBase, 1); + free(State); +} + +void *VM8086_Allocate(tVM8086 *State, int Size, Uint16 *Segment, Uint16 *Offset) +{ + int i, j, base = 0; + int nBlocks, rem; + Uint32 bmp; + + Size = (Size + 127) & ~127; + nBlocks = Size >> 7; + + if(Size > 4096) return NULL; + + for( i = 0; i < VM8086_PAGES_PER_INST; i++ ) + { + if( State->Internal->AllocatedPages[i].VirtBase == 0 ) continue; + bmp = State->Internal->AllocatedPages[i].Bitmap; + rem = nBlocks; + base = 0; + // Scan the bitmap for a free block + for( j = 0; j < 32-nBlocks; j++ ) { + if( bmp & (1 << j) ) { + base = 0; + rem = nBlocks; + } + else { + rem --; + if(rem == 0) // Goodie, there's a gap + { + for( j = 0; j < nBlocks; j++ ) + State->Internal->AllocatedPages[i].Bitmap |= 1 << (base + j); + *Segment = State->Internal->AllocatedPages[i].PhysAddr / 16 + base * 8; + *Offset = 0; + return (void*)( State->Internal->AllocatedPages[i].VirtBase + base * 128 ); + } + } + } + } + + // No pages with free space?, allocate a new one + for( i = 0; i < VM8086_PAGES_PER_INST; i++ ) + { + if( State->Internal->AllocatedPages[i].VirtBase == 0 ) break; + } + // Darn, we can't allocate any more + if( i == VM8086_PAGES_PER_INST ) { + Log_Warning("VM8086", "Out of pages in %p", State); + return NULL; + } + + State->Internal->AllocatedPages[i].VirtBase = MM_AllocDMA( + 1, 20, &State->Internal->AllocatedPages[i].PhysAddr); + State->Internal->AllocatedPages[i].Bitmap = 0; + + for( j = 0; j < nBlocks; j++ ) + State->Internal->AllocatedPages[i].Bitmap |= 1 << j; + *Segment = State->Internal->AllocatedPages[i].PhysAddr / 16; + *Offset = 0; + return (void*) State->Internal->AllocatedPages[i].VirtBase; +} + +void *VM8086_GetPointer(tVM8086 *State, Uint16 Segment, Uint16 Offset) +{ + return (void*)( KERNEL_BASE + Segment*16 + Offset ); +} + +void VM8086_Int(tVM8086 *State, Uint8 Interrupt) +{ + State->IP = *(Uint16*)(KERNEL_BASE+4*Interrupt); + State->CS = *(Uint16*)(KERNEL_BASE+4*Interrupt+2); + + LOCK( &glVM8086_Process ); + + gpVM8086_State = State; + gVM8086_CallingThread = Threads_GetTID(); + Threads_WakeTID( gVM8086_WorkerPID ); + while( gpVM8086_State != NULL ) + Threads_Sleep(); + + RELEASE( &glVM8086_Process ); +} diff --git a/Kernel/binary.c b/Kernel/binary.c index 0cd0bf3c..77309f38 100644 --- a/Kernel/binary.c +++ b/Kernel/binary.c @@ -24,7 +24,6 @@ typedef struct sKernelBin { // === IMPORTS === extern int Proc_Clone(Uint *Err, Uint Flags); -extern void Threads_SetName(char *Name); extern char *Threads_GetName(int ID); extern void Threads_Exit(int, int); extern Uint MM_ClearUser(); diff --git a/Kernel/drv/kb.c b/Kernel/drv/kb.c index 65d340e9..950f7228 100644 --- a/Kernel/drv/kb.c +++ b/Kernel/drv/kb.c @@ -11,6 +11,7 @@ // === CONSTANTS === #define KB_BUFFER_SIZE 1024 +#define USE_KERNEL_MAGIC 1 // === IMPORTS === void Threads_Dump(); @@ -83,6 +84,7 @@ void KB_IRQHandler() //if( inportb(0x64) & 0x20 ) return; scancode = inb(0x60); // Read from the keyboard's data buffer + Log_Debug("KB", "scancode = %02x"); //Log("KB_IRQHandler: scancode = 0x%02x", scancode); @@ -169,8 +171,14 @@ void KB_IRQHandler() // --- Check for Kernel Magic Combos #if USE_KERNEL_MAGIC - if(ch == KEY_LCTRL) gbKB_MagicState |= 1; - if(ch == KEY_LALT) gbKB_MagicState |= 2; + if(ch == KEY_LCTRL) { + gbKB_MagicState |= 1; + Log_Log("KB", "Kernel Magic LCTRL Down\n"); + } + if(ch == KEY_LALT) { + gbKB_MagicState |= 2; + Log_Log("KB", "Kernel Magic LALT Down\n"); + } if(gbKB_MagicState == 3) { switch(ch) diff --git a/Kernel/include/acess.h b/Kernel/include/acess.h index efa487ca..7afdb5e1 100644 --- a/Kernel/include/acess.h +++ b/Kernel/include/acess.h @@ -224,7 +224,7 @@ extern void MM_FreeTemp(tVAddr VAddr); * \param PAddr Physical address to map in * \param Number Number of pages to map */ -extern tVAddr MM_MapHWPage(tPAddr PAddr, Uint Number); +extern tVAddr MM_MapHWPages(tPAddr PAddr, Uint Number); /** * \brief Allocates DMA physical memory * \param Pages Number of pages required @@ -238,7 +238,7 @@ extern tVAddr MM_AllocDMA(int Pages, int MaxBits, tPAddr *PhysAddr); * \param VAddr Virtual address allocate by ::MM_MapHWPage or ::MM_AllocDMA * \param Number Number of pages to free */ -extern void MM_UnmapHWPage(tVAddr VAddr, Uint Number); +extern void MM_UnmapHWPages(tVAddr VAddr, Uint Number); /** * \brief Allocate a single physical page * \return Physical address allocated @@ -381,12 +381,14 @@ extern int Proc_Spawn(char *Path); extern void Threads_Exit(); extern void Threads_Yield(); extern void Threads_Sleep(); +extern void Threads_WakeTID(tTID Thread); extern tPID Threads_GetPID(); extern tTID Threads_GetTID(); extern tUID Threads_GetUID(); extern tGID Threads_GetGID(); extern int SpawnTask(tThreadFunction Function, void *Arg); extern Uint *Threads_GetCfgPtr(int Id); +extern int Threads_SetName(char *NewName); /** * \} */ diff --git a/Kernel/include/threads.h b/Kernel/include/threads.h index 9c5ebe75..b55fe0e0 100644 --- a/Kernel/include/threads.h +++ b/Kernel/include/threads.h @@ -19,7 +19,7 @@ typedef struct sThread // --- threads.c's struct sThread *Next; //!< Next thread in list tSpinlock IsLocked; //!< Thread's spinlock - int Status; //!< Thread Status + volatile int Status; //!< Thread Status int RetStatus; //!< Return Status Uint TID; //!< Thread ID diff --git a/Kernel/threads.c b/Kernel/threads.c index 075350dd..1ab70296 100644 --- a/Kernel/threads.c +++ b/Kernel/threads.c @@ -25,7 +25,7 @@ extern int Proc_Clone(Uint *Err, Uint Flags); // === PROTOTYPES === void Threads_Init(); -void Threads_SetName(char *NewName); + int Threads_SetName(char *NewName); char *Threads_GetName(int ID); void Threads_SetTickets(int Num); tThread *Threads_CloneTCB(Uint *Err, Uint Flags); @@ -118,13 +118,14 @@ void Threads_Init() * \fn void Threads_SetName(char *NewName) * \brief Sets the current thread's name */ -void Threads_SetName(char *NewName) +int Threads_SetName(char *NewName) { tThread *cur = Proc_GetCurThread(); if( IsHeap(cur->ThreadName) ) free( cur->ThreadName ); cur->ThreadName = malloc(strlen(NewName)+1); strcpy(cur->ThreadName, NewName); + return 0; } /** @@ -467,7 +468,7 @@ void Threads_Sleep() tThread *cur = Proc_GetCurThread(); tThread *thread; - Log("Proc_Sleep: %i going to sleep", cur->TID); + Log_Log("Threads", "%i going to sleep", cur->TID); // Acquire Spinlock LOCK( &giThreadListLock ); @@ -506,7 +507,9 @@ void Threads_Sleep() // Release Spinlock RELEASE( &giThreadListLock ); - while(cur->Status != THREAD_STAT_ACTIVE) HALT(); + while(cur->Status == THREAD_STAT_SLEEPING) HALT(); + //HALT(); + Log_Debug("VM8086", "What a lovely sleep"); } @@ -521,11 +524,14 @@ void Threads_Wake(tThread *Thread) { case THREAD_STAT_ACTIVE: break; case THREAD_STAT_SLEEPING: + Log_Log("Threads", "Waking %i (%p) from sleeping", Thread->TID, Thread); LOCK( &giThreadListLock ); prev = Threads_int_GetPrev(&gSleepingThreads, Thread); prev->Next = Thread->Next; // Remove from sleeping queue Thread->Next = gActiveThreads; // Add to active queue gActiveThreads = Thread; + giNumActiveThreads ++; + giTotalTickets += Thread->NumTickets; Thread->Status = THREAD_STAT_ACTIVE; RELEASE( &giThreadListLock ); break; @@ -541,6 +547,11 @@ void Threads_Wake(tThread *Thread) } } +void Threads_WakeTID(tTID Thread) +{ + Threads_Wake( Threads_GetThread(Thread) ); +} + /** * \fn void Threads_AddActive(tThread *Thread) * \brief Adds a thread to the active queue @@ -690,10 +701,15 @@ tThread *Threads_GetNextToRun(int CPU) int ticket; int number; - if(giNumActiveThreads == 0) return NULL; + if(giNumActiveThreads == 0) { + //Log_Debug("Threads", "CPU%i has no threads to run", CPU); + return NULL; + } // Special case: 1 thread if(giNumActiveThreads == 1) { + //Log_Debug("Threads", "CPU%i has only one thread %i %s", + // CPU, gActiveThreads->TID, gActiveThreads->ThreadName); return gActiveThreads; } @@ -721,6 +737,9 @@ tThread *Threads_GetNextToRun(int CPU) giTotalTickets, number); } + //Log_Debug("Threads", "Switching CPU%i to %p (%s)", + // CPU, thread, thread->ThreadName); + return thread; } diff --git a/Makefile b/Makefile index 9023afec..ba53f122 100644 --- a/Makefile +++ b/Makefile @@ -11,34 +11,36 @@ SUBMAKE = $(MAKE) --no-print-directory MODULES += $(DYNMODS) -USRLIBS = crt0.o acess.ld ld-acess.so libacess.so libgcc.so libc.so -USRAPPS = init login CLIShell cat ls mount ifconfig +USRLIBS := crt0.o acess.ld ld-acess.so libacess.so libgcc.so libc.so +USRAPPS := init login CLIShell cat ls mount ifconfig -ALL_MODULES = $(addprefix all-,$(MODULES)) -ALL_USRLIBS = $(addprefix all-,$(USRLIBS)) -ALL_USRAPPS = $(addprefix all-,$(USRAPPS)) -CLEAN_MODULES = $(addprefix clean-,$(MODULES)) -CLEAN_USRLIBS = $(addprefix clean-,$(USRLIBS)) -CLEAN_USRAPPS = $(addprefix clean-,$(USRAPPS)) -INSTALL_MODULES = $(addprefix install-,$(MODULES)) -INSTALL_USRLIBS = $(addprefix install-,$(USRLIBS)) -INSTALL_USRAPPS = $(addprefix install-,$(USRAPPS)) -ALLINSTALL_MODULES = $(addprefix allinstall-,$(MODULES)) -ALLINSTALL_USRLIBS = $(addprefix allinstall-,$(USRLIBS)) -ALLINSTALL_USRAPPS = $(addprefix allinstall-,$(USRAPPS)) +#ALL_DYNMODS = $(addprefix all-,$(DYNMODS)) +ALL_MODULES := $(addprefix all-,$(MODULES)) +ALL_USRLIBS := $(addprefix all-,$(USRLIBS)) +ALL_USRAPPS := $(addprefix all-,$(USRAPPS)) +CLEAN_MODULES := $(addprefix clean-,$(MODULES)) +CLEAN_USRLIBS := $(addprefix clean-,$(USRLIBS)) +CLEAN_USRAPPS := $(addprefix clean-,$(USRAPPS)) +INSTALL_MODULES := $(addprefix install-,$(MODULES)) +INSTALL_USRLIBS := $(addprefix install-,$(USRLIBS)) +INSTALL_USRAPPS := $(addprefix install-,$(USRAPPS)) +AI_DYNMODS := $(addprefix allinstall-,$(DYNMODS)) +AI_MODULES := $(addprefix allinstall-,$(MODULES)) +AI_USRLIBS := $(addprefix allinstall-,$(USRLIBS)) +AI_USRAPPS := $(addprefix allinstall-,$(USRAPPS)) .PHONY: all clean install \ $(ALL_MODULES) all-Kernel $(ALL_USRLIBS) $(ALL_USRAPPS) \ - $(ALLINSTALL_MODULES) allinstall-Kernel $(ALLINSTALL_USRLIBS) $(ALLINSTALL_USRAPPS) \ + $(AI_MODULES) allinstall-Kernel $(AI_USRLIBS) $(AI_USRAPPS) \ $(CLEAN_MODULES) clean-Kernel $(CLEAN_USRLIBS) $(CLEAN_USRAPPS) \ $(INSTALL_MODULES) install-Kernel $(INSTALL_USRLIBS) $(INSTALL_USRAPPS) -kmode: $(ALLINSTALL_MODULES) allinstall-Kernel +kmode: $(AI_MODULES) $(AI_DYNMODS) allinstall-Kernel -all: $(ALL_MODULES) all-Kernel $(ALL_USRLIBS) $(ALL_USRAPPS) -all-install: $(ALLINSTALL_MODULES) allinstall-Kernel $(ALLINSTALL_USRLIBS) $(ALLINSTALL_USRAPPS) -clean: $(CLEAN_MODULES) clean-Kernel $(CLEAN_USRLIBS) $(CLEAN_USRAPPS) -install: $(INSTALL_MODULES) install-Kernel $(INSTALL_USRLIBS) $(INSTALL_USRAPPS) +all: $(ALL_DYNMODS) $(ALL_MODULES) all-Kernel $(ALL_USRLIBS) $(ALL_USRAPPS) +all-install: $(AI_DYNMODS) $(AI_MODULES) allinstall-Kernel $(AI_USRLIBS) $(AI_USRAPPS) +clean: $(CLEAN_DYNMODS) $(CLEAN_MODULES) clean-Kernel $(CLEAN_USRLIBS) $(CLEAN_USRAPPS) +install: $(INSTALL_DYNMODS) $(INSTALL_MODULES) install-Kernel $(INSTALL_USRLIBS) $(INSTALL_USRAPPS) # Compile Only $(ALL_MODULES): all-%: @@ -51,13 +53,15 @@ $(ALL_USRAPPS): all-%: @echo === User Application: $* && $(SUBMAKE) all -C Usermode/Applications/$*_src # Compile & Install -$(ALLINSTALL_MODULES): allinstall-%: +#$(AI_DYNMODS): allinstall-%: +# @echo === Dynamic Module: $* && STATIC_MODULE=yes $(SUBMAKE) all install -C Modules/$* +$(AI_MODULES): allinstall-%: @echo === Module: $* && $(SUBMAKE) all install -C Modules/$* allinstall-Kernel: @echo === Kernel && $(SUBMAKE) all install -C Kernel -$(ALLINSTALL_USRLIBS): allinstall-%: +$(AI_USRLIBS): allinstall-%: @echo === User Library: $* && $(SUBMAKE) all install -C Usermode/Libraries/$*_src -$(ALLINSTALL_USRAPPS): allinstall-%: +$(AI_USRAPPS): allinstall-%: @echo === User Application: $* && $(SUBMAKE) all install -C Usermode/Applications/$*_src # Clean up compilation diff --git a/Makefile.cfg b/Makefile.cfg index e4ae222e..51c4802d 100644 --- a/Makefile.cfg +++ b/Makefile.cfg @@ -27,11 +27,12 @@ FILESYSTEMS = DRIVERS = MODULES = Storage/ATA Storage/FDD MODULES += Network/NE2000 +MODULES += Display/VESA #MODULES += Display/BochsGA MODULES += Filesystems/Ext2 MODULES += Filesystems/FAT MODULES += IPStack -DYNMODS = USB Interfaces/UDI +DYNMODS = USB/Core Interfaces/UDI #DISTROOT = /mnt/AcessHDD/Acess2 #DISTROOT = ~/Projects/Acess2/Filesystem diff --git a/Modules/Display/VESA/Makefile b/Modules/Display/VESA/Makefile new file mode 100644 index 00000000..d8da2334 --- /dev/null +++ b/Modules/Display/VESA/Makefile @@ -0,0 +1,7 @@ +# +# + +OBJ = main.o +NAME = VESA + +-include ../Makefile.tpl diff --git a/Modules/Display/VESA/common.h b/Modules/Display/VESA/common.h new file mode 100644 index 00000000..eeaddd56 --- /dev/null +++ b/Modules/Display/VESA/common.h @@ -0,0 +1,59 @@ +/** + */ +#ifndef _COMMON_H_ +#define _COMMON_H_ + +// === TYPES === +typedef struct sFarPtr +{ + Uint16 ofs; + Uint16 seg; +} tFarPtr; + +typedef struct sVesa_Mode +{ + Uint16 code; + Uint16 width, height; + Uint16 pitch, bpp; + Uint16 flags; + Uint32 fbSize; + Uint32 framebuffer; +} tVesa_Mode; + +typedef struct sVesa_CallModeInfo +{ + Uint16 attributes; + Uint8 winA,winB; + Uint16 granularity; + Uint16 winsize; + Uint16 segmentA, segmentB; + tFarPtr realFctPtr; + Uint16 pitch; // Bytes per scanline + + Uint16 Xres, Yres; + Uint8 Wchar, Ychar, planes, bpp, banks; + Uint8 memory_model, bank_size, image_pages; + Uint8 reserved0; + + Uint8 red_mask, red_position; + Uint8 green_mask, green_position; + Uint8 blue_mask, blue_position; + Uint8 rsv_mask, rsv_position; + Uint8 directcolor_attributes; + + Uint32 physbase; // Your LFB address ;) + Uint32 reserved1; + Sint16 reserved2; +} tVesa_CallModeInfo; + +typedef struct sVesa_CallInfo +{ + char signature[4]; // == "VESA" + Uint16 Version; // == 0x0300 for Vesa 3.0 + tFarPtr OEMString; // isa vbeFarPtr + Uint8 Capabilities[4]; + tFarPtr VideoModes; // isa vbeParPtr + Uint16 TotalMemory; // as # of 64KB blocks +} tVesa_CallInfo; + +#endif diff --git a/Modules/Display/VESA/main.c b/Modules/Display/VESA/main.c new file mode 100644 index 00000000..216fcd1d --- /dev/null +++ b/Modules/Display/VESA/main.c @@ -0,0 +1,286 @@ +/* + * AcessOS 1 + * Video BIOS Extensions (Vesa) Driver + */ +#define DEBUG 0 +#define VERSION 0x100 + +#include +#include +#include +#include +#include +#include +#include "common.h" + +// === CONSTANTS === +#define FLAG_LFB 0x1 + +// === PROTOTYPES === + int Vesa_Install(char **Arguments); +Uint64 Vesa_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer); +Uint64 Vesa_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer); + int Vesa_Ioctl(tVFS_Node *Node, int ID, void *Data); + int Vesa_Int_SetMode(int Mode); + int Vesa_Int_FindMode(tVideo_IOCtl_Mode *data); + int Vesa_Int_ModeInfo(tVideo_IOCtl_Mode *data); + +// === GLOBALS === +MODULE_DEFINE(0, VERSION, Vesa, Vesa_Install, NULL, "PCI", "VM8086", NULL); +tDevFS_Driver gVesa_DriverStruct = { + NULL, "VESA", + { + .Read = Vesa_Read, + .Write = Vesa_Write, + .IOCtl = Vesa_Ioctl + } +}; +tSpinlock glVesa_Lock; +tVM8086 *gpVesa_BiosState; + int giVesaCurrentMode = -1; + int giVesaDriverId = -1; +char *gVesaFramebuffer = (void*)0xC00A0000; +tVesa_Mode *gVesa_Modes; + int giVesaModeCount = 0; + int giVesaPageCount = 0; + +//CODE +int Vesa_Install(char **Arguments) +{ + tVesa_CallInfo *info; + tFarPtr infoPtr; + tVesa_CallModeInfo *modeinfo; + tFarPtr modeinfoPtr; + Uint16 *modes; + int i; + + // Allocate Info Block + gpVesa_BiosState = VM8086_Init(); + info = VM8086_Allocate(gpVesa_BiosState, 512, &infoPtr.seg, &infoPtr.ofs); + modeinfo = VM8086_Allocate(gpVesa_BiosState, 512, &modeinfoPtr.seg, &modeinfoPtr.ofs); + // Set Requested Version + memcpy(info->signature, "VBE2", 4); + // Set Registers + gpVesa_BiosState->AX = 0x4F00; + gpVesa_BiosState->ES = infoPtr.seg; gpVesa_BiosState->DI = infoPtr.ofs; + // Call Interrupt + VM8086_Int(gpVesa_BiosState, 0x10); + if(gpVesa_BiosState->AX != 0x004F) { + Log_Warning("Vesa", "Vesa_Install - VESA/VBE Unsupported (AX = 0x%x)\n", gpVesa_BiosState->AX); + return MODULE_ERR_NOTNEEDED; + } + + modes = (Uint16 *) VM8086_GetPointer(gpVesa_BiosState, info->VideoModes.seg, info->VideoModes.ofs); + + // Read Modes + for( giVesaModeCount = 1; modes[giVesaModeCount] != 0xFFFF; giVesaModeCount++ ); + gVesa_Modes = (tVesa_Mode *)malloc( giVesaModeCount * sizeof(tVesa_Mode) ); + + // Insert Text Mode + gVesa_Modes[0].width = 80; + gVesa_Modes[0].height = 25; + gVesa_Modes[0].bpp = 4; + gVesa_Modes[0].code = 0x3; + + for( i = 1; i < giVesaModeCount; i++ ) + { + gVesa_Modes[i].code = modes[i]; + // Get Mode info + gpVesa_BiosState->AX = 0x4F01; + gpVesa_BiosState->CX = gVesa_Modes[i].code; + gpVesa_BiosState->ES = modeinfoPtr.seg; + gpVesa_BiosState->DI = modeinfoPtr.ofs; + VM8086_Int(gpVesa_BiosState, 0x10); + + // Parse Info + gVesa_Modes[i].flags = 0; + if ( (modeinfo->attributes & 0x90) == 0x90 ) + { + gVesa_Modes[i].flags |= FLAG_LFB; + gVesa_Modes[i].framebuffer = modeinfo->physbase; + gVesa_Modes[i].fbSize = modeinfo->Xres*modeinfo->Yres*modeinfo->bpp/8; + } else { + gVesa_Modes[i].framebuffer = 0; + gVesa_Modes[i].fbSize = 0; + } + + gVesa_Modes[i].width = modeinfo->Xres; + gVesa_Modes[i].height = modeinfo->Yres; + gVesa_Modes[i].bpp = modeinfo->bpp; + + #if DEBUG + LogF(" Vesa_Install: 0x%x - %ix%ix%i\n", + gVesa_Modes[i].code, gVesa_Modes[i].width, gVesa_Modes[i].height, gVesa_Modes[i].bpp); + #endif + } + + + // Install Device + giVesaDriverId = DevFS_AddDevice( &gVesa_DriverStruct ); + if(giVesaDriverId == -1) return MODULE_ERR_MISC; + + return MODULE_ERR_OK; +} + +/* Read from the framebuffer + */ +Uint64 Vesa_Read(tVFS_Node *Node, Uint64 off, Uint64 len, void *buffer) +{ + #if DEBUG >= 2 + LogF("Vesa_Read: () - NULL\n"); + #endif + return 0; +} + +/** + * \brief Write to the framebuffer + */ +Uint64 Vesa_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) +{ + ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Bufffer); + + if(Buffer == NULL) { + LEAVE('i', 0); + return 0; + } + + if( gVesa_Modes[giVesaCurrentMode].framebuffer == 0 ) { + Log_Warning("VESA", "Vesa_Write - Non-LFB Modes not yet supported."); + LEAVE('i', 0); + return 0; + } + if(gVesa_Modes[giVesaCurrentMode].fbSize < Offset+Length) + { + Log_Warning("VESA", "Vesa_Write - Framebuffer Overflow"); + LEAVE('i', 0); + return 0; + } + + memcpy(gVesaFramebuffer + Offset, Buffer, Length); + + LEAVE('X', Length); + return Length; +} + +/** + * \fn int Vesa_Ioctl(vfs_node *node, int id, void *data) + * \brief Handle messages to the device + */ +int Vesa_Ioctl(tVFS_Node *Node, int ID, void *Data) +{ + switch(ID) + { + case DRV_IOCTL_TYPE: return DRV_TYPE_VIDEO; + case DRV_IOCTL_IDENT: memcpy("VESA", Data, 4); return 1; + case DRV_IOCTL_VERSION: return VERSION; + + case VIDEO_IOCTL_GETSETMODE: + if( !Data ) return giVesaCurrentMode; + return Vesa_Int_SetMode( *(int*)Data ); + + case VIDEO_IOCTL_FINDMODE: + return Vesa_Int_FindMode((tVideo_IOCtl_Mode*)Data); + case VIDEO_IOCTL_MODEINFO: + return Vesa_Int_ModeInfo((tVideo_IOCtl_Mode*)Data); + + case VIDEO_IOCTL_REQLFB: // Request Linear Framebuffer + return 0; + } + return 0; +} + +int Vesa_Int_SetMode(int mode) +{ + #if DEBUG + LogF("Vesa_Int_SetMode: (mode=%i)\n", mode); + #endif + + // Sanity Check values + if(mode < 0 || mode > giVesaModeCount) return -1; + + // Check for fast return + if(mode == giVesaCurrentMode) return 1; + + LOCK( &glVesa_Lock ); + + gpVesa_BiosState->AX = 0x4F02; + gpVesa_BiosState->BX = gVesa_Modes[mode].code; + if(gVesa_Modes[mode].flags & FLAG_LFB) { + LogF(" Vesa_Int_SetMode: Using LFB\n"); + gpVesa_BiosState->BX |= 0x4000; // Bit 14 - Use LFB + } + + // Set Mode + VM8086_Int(gpVesa_BiosState, 0x10); + + // Map Framebuffer + MM_UnmapHWPages((tVAddr)gVesaFramebuffer, giVesaPageCount); + giVesaPageCount = (gVesa_Modes[mode].fbSize + 0xFFF) >> 12; + gVesaFramebuffer = (void*)MM_MapHWPages(gVesa_Modes[mode].framebuffer, giVesaPageCount); + + LogF(" Vesa_Int_SetMode: Fb (Phys) = 0x%x\n", gVesa_Modes[mode].framebuffer); + LogF(" Vesa_Int_SetMode: Fb (Virt) = 0x%x\n", gVesaFramebuffer); + + // Record Mode Set + giVesaCurrentMode = mode; + + RELEASE( &glVesa_Lock ); + + return 1; +} + +int Vesa_Int_FindMode(tVideo_IOCtl_Mode *data) +{ + int i; + int best = -1, bestFactor = 1000; + int factor, tmp; + #if DEBUG + LogF("Vesa_Int_FindMode: (data={width:%i,height:%i,bpp:%i})\n", data->width, data->height, data->bpp); + #endif + for(i=0;i= 2 + LogF("Mode %i (%ix%ix%i), ", i, gVesa_Modes[i].width, gVesa_Modes[i].height, gVesa_Modes[i].bpp); + #endif + + if(gVesa_Modes[i].width == data->width + && gVesa_Modes[i].height == data->height + && gVesa_Modes[i].bpp == data->bpp) + { + #if DEBUG >= 2 + LogF("Perfect!\n"); + #endif + best = i; + break; + } + + tmp = gVesa_Modes[i].width * gVesa_Modes[i].height * gVesa_Modes[i].bpp; + tmp -= data->width * data->height * data->bpp; + tmp = tmp < 0 ? -tmp : tmp; + factor = tmp * 100 / (data->width * data->height * data->bpp); + + #if DEBUG >= 2 + LogF("factor = %i\n", factor); + #endif + + if(factor < bestFactor) + { + bestFactor = factor; + best = i; + } + } + data->id = best; + data->width = gVesa_Modes[best].width; + data->height = gVesa_Modes[best].height; + data->bpp = gVesa_Modes[best].bpp; + return best; +} + +int Vesa_Int_ModeInfo(tVideo_IOCtl_Mode *data) +{ + if(data->id < 0 || data->id > giVesaModeCount) return -1; + data->width = gVesa_Modes[data->id].width; + data->height = gVesa_Modes[data->id].height; + data->bpp = gVesa_Modes[data->id].bpp; + return 1; +} diff --git a/Modules/Makefile.tpl b/Modules/Makefile.tpl index 4341bdae..9a1b6e82 100644 --- a/Modules/Makefile.tpl +++ b/Modules/Makefile.tpl @@ -15,7 +15,7 @@ CPPFLAGS = -I$(ACESSDIR)/Kernel/include -I$(ACESSDIR)/Kernel/arch/$(ARCHDIR)/inc CFLAGS = -Wall -Werror -fno-stack-protector $(CPPFLAGS) -O3 OBJ := $(addsuffix .$(ARCH),$(OBJ)) -ifeq ($(CATEGORY),) +ifneq ($(CATEGORY),) BIN := ../$(CATEGORY)_$(NAME).kmd.$(ARCH) else BIN := ../$(NAME).kmd.$(ARCH) diff --git a/Modules/Network/Makefile.tpl b/Modules/Network/Makefile.tpl index 80c6d4dd..d5c0b3cc 100644 --- a/Modules/Network/Makefile.tpl +++ b/Modules/Network/Makefile.tpl @@ -1 +1,3 @@ +CATEGORY = Network + -include ../../Makefile.tpl diff --git a/Modules/Storage/ATA/main.c b/Modules/Storage/ATA/main.c index 9ad8898c..a1010a83 100644 --- a/Modules/Storage/ATA/main.c +++ b/Modules/Storage/ATA/main.c @@ -151,7 +151,7 @@ int ATA_SetupIO() if( gATA_BusMasterBase < 0x100000 ) gATA_BusMasterBasePtr = (void*)(0xC0000000|gATA_BusMasterBase); else - gATA_BusMasterBasePtr = (void*)( MM_MapHWPage( gATA_BusMasterBase, 1 ) + (gATA_BusMasterBase&0xFFF) ); + gATA_BusMasterBasePtr = (void*)( MM_MapHWPages( gATA_BusMasterBase, 1 ) + (gATA_BusMasterBase&0xFFF) ); LOG("gATA_BusMasterBasePtr = %p", gATA_BusMasterBasePtr); } else { diff --git a/Modules/USB/Core/Makefile b/Modules/USB/Core/Makefile index b4f400a5..af927313 100644 --- a/Modules/USB/Core/Makefile +++ b/Modules/USB/Core/Makefile @@ -2,6 +2,6 @@ # OBJ = main.o uhci.o -NAME = USB +NAME = Core -include ../Makefile.tpl -- 2.20.1