VM8086 Support, Starting on VESA Driver
authorJohn Hodge <[email protected]>
Fri, 2 Apr 2010 07:48:24 +0000 (15:48 +0800)
committerJohn Hodge <[email protected]>
Fri, 2 Apr 2010 07:48:24 +0000 (15:48 +0800)
- 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)

22 files changed:
Kernel/Makefile.BuildNum
Kernel/arch/x86/Makefile
Kernel/arch/x86/errors.c
Kernel/arch/x86/include/vm8086.h
Kernel/arch/x86/mm_phys.c
Kernel/arch/x86/mm_virt.c
Kernel/arch/x86/proc.c
Kernel/arch/x86/vm8086.c [new file with mode: 0644]
Kernel/binary.c
Kernel/drv/kb.c
Kernel/include/acess.h
Kernel/include/threads.h
Kernel/threads.c
Makefile
Makefile.cfg
Modules/Display/VESA/Makefile [new file with mode: 0644]
Modules/Display/VESA/common.h [new file with mode: 0644]
Modules/Display/VESA/main.c [new file with mode: 0644]
Modules/Makefile.tpl
Modules/Network/Makefile.tpl
Modules/Storage/ATA/main.c
Modules/USB/Core/Makefile

index dc7f7ff..a571286 100644 (file)
@@ -1 +1 @@
-BUILD_NUM = 1636
+BUILD_NUM = 1696
index 87dd2b2..708c8dc 100644 (file)
@@ -31,5 +31,5 @@ endif
 
 A_OBJ  = start.ao main.o lib.o desctab.ao errors.o irq.o
 A_OBJ += mm_phys.o mm_virt.o
-A_OBJ += proc.o time.o
+A_OBJ += proc.o time.o vm8086.o
 #A_OBJ += gdb_stub.o
index cfc7075..b53807a 100644 (file)
@@ -11,6 +11,7 @@
 
 // === IMPORTS ===
 extern void    MM_PageFault(Uint Addr, Uint ErrorCode, tRegs *Regs);
+extern void    VM8086_GPF(tRegs *Regs);
 extern void Threads_Dump();
 
 // === PROTOTYPES ===
@@ -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);
index cb2834c..353ad7a 100644 (file)
@@ -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
index 988a15e..f091c63 100644 (file)
@@ -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;
 }
 
index 958b9f1..6976c65 100644 (file)
@@ -895,10 +895,10 @@ void MM_FreeTemp(tVAddr VAddr)
 }
 
 /**
- * \fn tVAddr MM_MapHWPage(tPAddr PAddr, Uint Number)
+ * \fn tVAddr MM_MapHWPages(tPAddr PAddr, Uint Number)
  * \brief Allocates a contigous number of pages
  */
-tVAddr MM_MapHWPage(tPAddr PAddr, Uint Number)
+tVAddr MM_MapHWPages(tPAddr PAddr, Uint Number)
 {
         int    i, j;
        
@@ -962,7 +962,7 @@ tVAddr MM_AllocDMA(int Pages, int MaxBits, tPAddr *PhysAddr)
        {
                phys = MM_AllocPhys();
                *PhysAddr = phys;
-               ret = MM_MapHWPage(phys, 1);
+               ret = MM_MapHWPages(phys, 1);
                if(ret == 0) {
                        MM_DerefPhys(phys);
                        LEAVE('i', 0);
@@ -981,7 +981,7 @@ tVAddr MM_AllocDMA(int Pages, int MaxBits, tPAddr *PhysAddr)
        }
        
        // Allocated successfully, now map
-       ret = MM_MapHWPage(phys, Pages);
+       ret = MM_MapHWPages(phys, Pages);
        if( ret == 0 ) {
                // If it didn't map, free then return 0
                for(;Pages--;phys+=0x1000)
@@ -996,10 +996,10 @@ tVAddr MM_AllocDMA(int Pages, int MaxBits, tPAddr *PhysAddr)
 }
 
 /**
- * \fn void MM_UnmapHWPage(tVAddr VAddr, Uint Number)
+ * \fn void MM_UnmapHWPages(tVAddr VAddr, Uint Number)
  * \brief Unmap a hardware page
  */
-void MM_UnmapHWPage(tVAddr VAddr, Uint Number)
+void MM_UnmapHWPages(tVAddr VAddr, Uint Number)
 {
         int    i, j;
        // Sanity Check
@@ -1022,6 +1022,6 @@ void MM_UnmapHWPage(tVAddr VAddr, Uint Number)
 EXPORT(MM_GetPhysAddr);
 EXPORT(MM_Map);
 //EXPORT(MM_Unmap);
-EXPORT(MM_MapHWPage);
+EXPORT(MM_MapHWPages);
 EXPORT(MM_AllocDMA);
-EXPORT(MM_UnmapHWPage);
+EXPORT(MM_UnmapHWPages);
index a66a540..b2f7f8f 100644 (file)
@@ -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 (file)
index 0000000..abc08dc
--- /dev/null
@@ -0,0 +1,329 @@
+/*
+ * Acess2 VM8086 Driver
+ * - By John Hodge (thePowersGang)
+ */
+#include <acess.h>
+#include <vm8086.h>
+#include <modules.h>
+
+// === CONSTANTS ===
+#define VM8086_MAGIC_CS        0xFFFF
+#define VM8086_MAGIC_IP        0x0010
+#define VM8086_STACK_SEG       0x9F00
+#define VM8086_STACK_OFS       0x0AFE
+enum eVM8086_Opcodes
+{
+       VM8086_OP_PUSHF = 0x9C,
+       VM8086_OP_POPF  = 0x9D,
+       VM8086_OP_INT_I = 0xCD,
+       VM8086_OP_IRET  = 0xCF
+};
+#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 );
+}
index 0cd0bf3..77309f3 100644 (file)
@@ -24,7 +24,6 @@ typedef struct sKernelBin {
 \r
 // === IMPORTS ===\r
 extern int     Proc_Clone(Uint *Err, Uint Flags);\r
-extern void    Threads_SetName(char *Name);\r
 extern char    *Threads_GetName(int ID);\r
 extern void    Threads_Exit(int, int);\r
 extern Uint    MM_ClearUser();\r
index 65d340e..950f722 100644 (file)
@@ -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)
index efa487c..7afdb5e 100644 (file)
@@ -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);
 /**
  * \}
  */
index 9c5ebe7..b55fe0e 100644 (file)
@@ -19,7 +19,7 @@ typedef struct sThread
        // --- threads.c's
        struct sThread  *Next;  //!< Next thread in list
        tSpinlock       IsLocked;       //!< Thread's spinlock
-        int    Status;         //!< Thread Status
+       volatile int    Status;         //!< Thread Status
         int    RetStatus;      //!< Return Status
        
        Uint    TID;    //!< Thread ID
index 075350d..1ab7029 100644 (file)
@@ -25,7 +25,7 @@ extern int    Proc_Clone(Uint *Err, Uint Flags);
 
 // === PROTOTYPES ===
 void   Threads_Init();
-void   Threads_SetName(char *NewName);
+ int   Threads_SetName(char *NewName);
 char   *Threads_GetName(int ID);
 void   Threads_SetTickets(int Num);
 tThread        *Threads_CloneTCB(Uint *Err, Uint Flags);
@@ -118,13 +118,14 @@ void Threads_Init()
  * \fn void Threads_SetName(char *NewName)
  * \brief Sets the current thread's name
  */
-void Threads_SetName(char *NewName)
+int Threads_SetName(char *NewName)
 {
        tThread *cur = Proc_GetCurThread();
        if( IsHeap(cur->ThreadName) )
                free( cur->ThreadName );
        cur->ThreadName = malloc(strlen(NewName)+1);
        strcpy(cur->ThreadName, NewName);
+       return 0;
 }
 
 /**
@@ -467,7 +468,7 @@ void Threads_Sleep()
        tThread *cur = Proc_GetCurThread();
        tThread *thread;
        
-       Log("Proc_Sleep: %i going to sleep", cur->TID);
+       Log_Log("Threads", "%i going to sleep", cur->TID);
        
        // Acquire Spinlock
        LOCK( &giThreadListLock );
@@ -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;
 }
 
index 9023afe..ba53f12 100644 (file)
--- a/Makefile
+++ b/Makefile
 SUBMAKE = $(MAKE) --no-print-directory
 
 MODULES += $(DYNMODS)
-USRLIBS = crt0.o acess.ld ld-acess.so libacess.so libgcc.so libc.so
-USRAPPS = init login CLIShell cat ls mount ifconfig
+USRLIBS := crt0.o acess.ld ld-acess.so libacess.so libgcc.so libc.so
+USRAPPS := init login CLIShell cat ls mount ifconfig
 
-ALL_MODULES = $(addprefix all-,$(MODULES))
-ALL_USRLIBS = $(addprefix all-,$(USRLIBS))
-ALL_USRAPPS = $(addprefix all-,$(USRAPPS))
-CLEAN_MODULES = $(addprefix clean-,$(MODULES))
-CLEAN_USRLIBS = $(addprefix clean-,$(USRLIBS))
-CLEAN_USRAPPS = $(addprefix clean-,$(USRAPPS))
-INSTALL_MODULES = $(addprefix install-,$(MODULES))
-INSTALL_USRLIBS = $(addprefix install-,$(USRLIBS))
-INSTALL_USRAPPS = $(addprefix install-,$(USRAPPS))
-ALLINSTALL_MODULES = $(addprefix allinstall-,$(MODULES))
-ALLINSTALL_USRLIBS = $(addprefix allinstall-,$(USRLIBS))
-ALLINSTALL_USRAPPS = $(addprefix allinstall-,$(USRAPPS))
+#ALL_DYNMODS = $(addprefix all-,$(DYNMODS))
+ALL_MODULES := $(addprefix all-,$(MODULES))
+ALL_USRLIBS := $(addprefix all-,$(USRLIBS))
+ALL_USRAPPS := $(addprefix all-,$(USRAPPS))
+CLEAN_MODULES := $(addprefix clean-,$(MODULES))
+CLEAN_USRLIBS := $(addprefix clean-,$(USRLIBS))
+CLEAN_USRAPPS := $(addprefix clean-,$(USRAPPS))
+INSTALL_MODULES := $(addprefix install-,$(MODULES))
+INSTALL_USRLIBS := $(addprefix install-,$(USRLIBS))
+INSTALL_USRAPPS := $(addprefix install-,$(USRAPPS))
+AI_DYNMODS := $(addprefix allinstall-,$(DYNMODS))
+AI_MODULES := $(addprefix allinstall-,$(MODULES))
+AI_USRLIBS := $(addprefix allinstall-,$(USRLIBS))
+AI_USRAPPS := $(addprefix allinstall-,$(USRAPPS))
 
 .PHONY: all clean install \
        $(ALL_MODULES) all-Kernel $(ALL_USRLIBS) $(ALL_USRAPPS) \
-       $(ALLINSTALL_MODULES) allinstall-Kernel $(ALLINSTALL_USRLIBS) $(ALLINSTALL_USRAPPS) \
+       $(AI_MODULES) allinstall-Kernel $(AI_USRLIBS) $(AI_USRAPPS) \
        $(CLEAN_MODULES) clean-Kernel $(CLEAN_USRLIBS) $(CLEAN_USRAPPS) \
        $(INSTALL_MODULES) install-Kernel $(INSTALL_USRLIBS) $(INSTALL_USRAPPS)
 
-kmode: $(ALLINSTALL_MODULES) allinstall-Kernel
+kmode: $(AI_MODULES) $(AI_DYNMODS) allinstall-Kernel
 
-all:   $(ALL_MODULES) all-Kernel $(ALL_USRLIBS) $(ALL_USRAPPS)
-all-install:   $(ALLINSTALL_MODULES) allinstall-Kernel $(ALLINSTALL_USRLIBS) $(ALLINSTALL_USRAPPS)
-clean: $(CLEAN_MODULES) clean-Kernel $(CLEAN_USRLIBS) $(CLEAN_USRAPPS)
-install:       $(INSTALL_MODULES) install-Kernel $(INSTALL_USRLIBS) $(INSTALL_USRAPPS)
+all:   $(ALL_DYNMODS) $(ALL_MODULES) all-Kernel $(ALL_USRLIBS) $(ALL_USRAPPS)
+all-install:   $(AI_DYNMODS) $(AI_MODULES) allinstall-Kernel $(AI_USRLIBS) $(AI_USRAPPS)
+clean: $(CLEAN_DYNMODS) $(CLEAN_MODULES) clean-Kernel $(CLEAN_USRLIBS) $(CLEAN_USRAPPS)
+install:       $(INSTALL_DYNMODS) $(INSTALL_MODULES) install-Kernel $(INSTALL_USRLIBS) $(INSTALL_USRAPPS)
 
 # Compile Only
 $(ALL_MODULES): all-%:
@@ -51,13 +53,15 @@ $(ALL_USRAPPS): all-%:
        @echo === User Application: $* && $(SUBMAKE) all -C Usermode/Applications/$*_src
 
 # Compile & Install
-$(ALLINSTALL_MODULES): allinstall-%:
+#$(AI_DYNMODS): allinstall-%:
+#      @echo === Dynamic Module: $* && STATIC_MODULE=yes $(SUBMAKE) all install -C Modules/$*
+$(AI_MODULES): allinstall-%:
        @echo === Module: $* && $(SUBMAKE) all install -C Modules/$*
 allinstall-Kernel:
        @echo === Kernel && $(SUBMAKE) all install -C Kernel
-$(ALLINSTALL_USRLIBS): allinstall-%:
+$(AI_USRLIBS): allinstall-%:
        @echo === User Library: $* && $(SUBMAKE) all install -C Usermode/Libraries/$*_src
-$(ALLINSTALL_USRAPPS): allinstall-%:
+$(AI_USRAPPS): allinstall-%:
        @echo === User Application: $* && $(SUBMAKE) all install -C Usermode/Applications/$*_src
 
 # Clean up compilation
index e4ae222..51c4802 100644 (file)
@@ -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 (file)
index 0000000..d8da233
--- /dev/null
@@ -0,0 +1,7 @@
+#
+#
+
+OBJ = main.o
+NAME = VESA
+
+-include ../Makefile.tpl
diff --git a/Modules/Display/VESA/common.h b/Modules/Display/VESA/common.h
new file mode 100644 (file)
index 0000000..eeaddd5
--- /dev/null
@@ -0,0 +1,59 @@
+/**
+ */
+#ifndef _COMMON_H_
+#define _COMMON_H_
+
+// === TYPES ===
+typedef struct sFarPtr
+{
+       Uint16  ofs;
+       Uint16  seg;
+}      tFarPtr;
+
+typedef struct sVesa_Mode
+{
+       Uint16  code;
+       Uint16  width, height;
+       Uint16  pitch, bpp;
+       Uint16  flags;
+       Uint32  fbSize;
+       Uint32  framebuffer;
+}      tVesa_Mode;
+
+typedef struct sVesa_CallModeInfo
+{
+       Uint16  attributes;
+       Uint8   winA,winB;
+       Uint16  granularity;
+       Uint16  winsize;
+       Uint16  segmentA, segmentB;
+       tFarPtr realFctPtr;
+       Uint16  pitch;  // Bytes per scanline
+
+       Uint16  Xres, Yres;
+       Uint8   Wchar, Ychar, planes, bpp, banks;
+       Uint8   memory_model, bank_size, image_pages;
+       Uint8   reserved0;
+
+       Uint8   red_mask, red_position;
+       Uint8   green_mask, green_position;
+       Uint8   blue_mask, blue_position;
+       Uint8   rsv_mask, rsv_position;
+       Uint8   directcolor_attributes;
+
+       Uint32  physbase;  // Your LFB address ;)
+       Uint32  reserved1;
+       Sint16  reserved2;
+}      tVesa_CallModeInfo;
+
+typedef struct sVesa_CallInfo
+{
+   char                signature[4];           // == "VESA"
+   Uint16      Version;        // == 0x0300 for Vesa 3.0
+   tFarPtr     OEMString;      // isa vbeFarPtr
+   Uint8       Capabilities[4];        
+   tFarPtr     VideoModes;     // isa vbeParPtr
+   Uint16      TotalMemory;    // as # of 64KB blocks
+}      tVesa_CallInfo;
+
+#endif
diff --git a/Modules/Display/VESA/main.c b/Modules/Display/VESA/main.c
new file mode 100644 (file)
index 0000000..216fcd1
--- /dev/null
@@ -0,0 +1,286 @@
+/*\r
+ * AcessOS 1\r
+ * Video BIOS Extensions (Vesa) Driver\r
+ */\r
+#define DEBUG  0\r
+#define VERSION        0x100\r
+\r
+#include <acess.h>\r
+#include <vfs.h>\r
+#include <tpl_drv_video.h>\r
+#include <fs_devfs.h>\r
+#include <modules.h>\r
+#include <vm8086.h>\r
+#include "common.h"\r
+\r
+// === CONSTANTS ===\r
+#define        FLAG_LFB        0x1\r
+\r
+// === PROTOTYPES ===\r
+ int   Vesa_Install(char **Arguments);\r
+Uint64 Vesa_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);\r
+Uint64 Vesa_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);\r
+ int   Vesa_Ioctl(tVFS_Node *Node, int ID, void *Data);\r
+ int   Vesa_Int_SetMode(int Mode);\r
+ int   Vesa_Int_FindMode(tVideo_IOCtl_Mode *data);\r
+ int   Vesa_Int_ModeInfo(tVideo_IOCtl_Mode *data);\r
+\r
+// === GLOBALS ===\r
+MODULE_DEFINE(0, VERSION, Vesa, Vesa_Install, NULL, "PCI", "VM8086", NULL);\r
+tDevFS_Driver  gVesa_DriverStruct = {\r
+       NULL, "VESA",\r
+       {\r
+       .Read = Vesa_Read,\r
+       .Write = Vesa_Write,\r
+       .IOCtl = Vesa_Ioctl\r
+       }\r
+};\r
+tSpinlock      glVesa_Lock;\r
+tVM8086        *gpVesa_BiosState;\r
+ int   giVesaCurrentMode = -1;\r
+ int   giVesaDriverId = -1;\r
+char   *gVesaFramebuffer = (void*)0xC00A0000;\r
+tVesa_Mode     *gVesa_Modes;\r
+ int   giVesaModeCount = 0;\r
+ int   giVesaPageCount = 0;\r
+\r
+//CODE\r
+int Vesa_Install(char **Arguments)\r
+{\r
+       tVesa_CallInfo  *info;\r
+       tFarPtr infoPtr;\r
+       tVesa_CallModeInfo      *modeinfo;\r
+       tFarPtr modeinfoPtr;\r
+       Uint16  *modes;\r
+       int     i;\r
+       \r
+       // Allocate Info Block\r
+       gpVesa_BiosState = VM8086_Init();\r
+       info = VM8086_Allocate(gpVesa_BiosState, 512, &infoPtr.seg, &infoPtr.ofs);\r
+       modeinfo = VM8086_Allocate(gpVesa_BiosState, 512, &modeinfoPtr.seg, &modeinfoPtr.ofs);\r
+       // Set Requested Version\r
+       memcpy(info->signature, "VBE2", 4);\r
+       // Set Registers\r
+       gpVesa_BiosState->AX = 0x4F00;\r
+       gpVesa_BiosState->ES = infoPtr.seg;     gpVesa_BiosState->DI = infoPtr.ofs;\r
+       // Call Interrupt\r
+       VM8086_Int(gpVesa_BiosState, 0x10);\r
+       if(gpVesa_BiosState->AX != 0x004F) {\r
+               Log_Warning("Vesa", "Vesa_Install - VESA/VBE Unsupported (AX = 0x%x)\n", gpVesa_BiosState->AX);\r
+               return MODULE_ERR_NOTNEEDED;\r
+       }\r
+       \r
+       modes = (Uint16 *) VM8086_GetPointer(gpVesa_BiosState, info->VideoModes.seg, info->VideoModes.ofs);\r
+       \r
+       // Read Modes\r
+       for( giVesaModeCount = 1; modes[giVesaModeCount] != 0xFFFF; giVesaModeCount++ );\r
+       gVesa_Modes = (tVesa_Mode *)malloc( giVesaModeCount * sizeof(tVesa_Mode) );\r
+       \r
+       // Insert Text Mode\r
+       gVesa_Modes[0].width = 80;\r
+       gVesa_Modes[0].height = 25;\r
+       gVesa_Modes[0].bpp = 4;\r
+       gVesa_Modes[0].code = 0x3;\r
+       \r
+       for( i = 1; i < giVesaModeCount; i++ )\r
+       {\r
+               gVesa_Modes[i].code = modes[i];\r
+               // Get Mode info\r
+               gpVesa_BiosState->AX = 0x4F01;\r
+               gpVesa_BiosState->CX = gVesa_Modes[i].code;\r
+               gpVesa_BiosState->ES = modeinfoPtr.seg;\r
+               gpVesa_BiosState->DI = modeinfoPtr.ofs;\r
+               VM8086_Int(gpVesa_BiosState, 0x10);\r
+               \r
+               // Parse Info\r
+               gVesa_Modes[i].flags = 0;\r
+               if ( (modeinfo->attributes & 0x90) == 0x90 )\r
+               {\r
+                       gVesa_Modes[i].flags |= FLAG_LFB;\r
+                       gVesa_Modes[i].framebuffer = modeinfo->physbase;\r
+                       gVesa_Modes[i].fbSize = modeinfo->Xres*modeinfo->Yres*modeinfo->bpp/8;\r
+               } else {\r
+                       gVesa_Modes[i].framebuffer = 0;\r
+                       gVesa_Modes[i].fbSize = 0;\r
+               }\r
+               \r
+               gVesa_Modes[i].width = modeinfo->Xres;\r
+               gVesa_Modes[i].height = modeinfo->Yres;\r
+               gVesa_Modes[i].bpp = modeinfo->bpp;\r
+               \r
+               #if DEBUG\r
+               LogF(" Vesa_Install: 0x%x - %ix%ix%i\n",\r
+                       gVesa_Modes[i].code, gVesa_Modes[i].width, gVesa_Modes[i].height, gVesa_Modes[i].bpp);\r
+               #endif\r
+       }\r
+       \r
+       \r
+       // Install Device\r
+       giVesaDriverId = DevFS_AddDevice( &gVesa_DriverStruct );\r
+       if(giVesaDriverId == -1)        return MODULE_ERR_MISC;\r
+       \r
+       return MODULE_ERR_OK;\r
+}\r
+\r
+/* Read from the framebuffer\r
+ */\r
+Uint64 Vesa_Read(tVFS_Node *Node, Uint64 off, Uint64 len, void *buffer)\r
+{\r
+       #if DEBUG >= 2\r
+       LogF("Vesa_Read: () - NULL\n");\r
+       #endif\r
+       return 0;\r
+}\r
+\r
+/**\r
+ * \brief Write to the framebuffer\r
+ */\r
+Uint64 Vesa_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)\r
+{\r
+       ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Bufffer);\r
+\r
+       if(Buffer == NULL) {\r
+               LEAVE('i', 0);\r
+               return 0;\r
+       }\r
+\r
+       if( gVesa_Modes[giVesaCurrentMode].framebuffer == 0 ) {\r
+               Log_Warning("VESA", "Vesa_Write - Non-LFB Modes not yet supported.");\r
+               LEAVE('i', 0);\r
+               return 0;\r
+       }\r
+       if(gVesa_Modes[giVesaCurrentMode].fbSize < Offset+Length)\r
+       {\r
+               Log_Warning("VESA", "Vesa_Write - Framebuffer Overflow");\r
+               LEAVE('i', 0);\r
+               return 0;\r
+       }\r
+       \r
+       memcpy(gVesaFramebuffer + Offset, Buffer, Length);\r
+       \r
+       LEAVE('X', Length);\r
+       return Length;\r
+}\r
+\r
+/**\r
+ * \fn int Vesa_Ioctl(vfs_node *node, int id, void *data)\r
+ * \brief Handle messages to the device\r
+ */\r
+int Vesa_Ioctl(tVFS_Node *Node, int ID, void *Data)\r
+{\r
+       switch(ID)\r
+       {\r
+       case DRV_IOCTL_TYPE:    return DRV_TYPE_VIDEO;\r
+       case DRV_IOCTL_IDENT:   memcpy("VESA", Data, 4);        return 1;\r
+       case DRV_IOCTL_VERSION: return VERSION;\r
+       \r
+       case VIDEO_IOCTL_GETSETMODE:\r
+               if( !Data )     return giVesaCurrentMode;\r
+               return Vesa_Int_SetMode( *(int*)Data );\r
+       \r
+       case VIDEO_IOCTL_FINDMODE:\r
+               return Vesa_Int_FindMode((tVideo_IOCtl_Mode*)Data);\r
+       case VIDEO_IOCTL_MODEINFO:\r
+               return Vesa_Int_ModeInfo((tVideo_IOCtl_Mode*)Data);\r
+       \r
+       case VIDEO_IOCTL_REQLFB:        // Request Linear Framebuffer\r
+               return 0;\r
+       }\r
+       return 0;\r
+}\r
+\r
+int Vesa_Int_SetMode(int mode)\r
+{      \r
+       #if DEBUG\r
+       LogF("Vesa_Int_SetMode: (mode=%i)\n", mode);\r
+       #endif\r
+       \r
+       // Sanity Check values\r
+       if(mode < 0 || mode > giVesaModeCount)  return -1;\r
+       \r
+       // Check for fast return\r
+       if(mode == giVesaCurrentMode)   return 1;\r
+       \r
+       LOCK( &glVesa_Lock );\r
+       \r
+       gpVesa_BiosState->AX = 0x4F02;\r
+       gpVesa_BiosState->BX = gVesa_Modes[mode].code;\r
+       if(gVesa_Modes[mode].flags & FLAG_LFB) {\r
+               LogF(" Vesa_Int_SetMode: Using LFB\n");\r
+               gpVesa_BiosState->BX |= 0x4000; // Bit 14 - Use LFB\r
+       }\r
+       \r
+       // Set Mode\r
+       VM8086_Int(gpVesa_BiosState, 0x10);\r
+       \r
+       // Map Framebuffer\r
+       MM_UnmapHWPages((tVAddr)gVesaFramebuffer, giVesaPageCount);\r
+       giVesaPageCount = (gVesa_Modes[mode].fbSize + 0xFFF) >> 12;\r
+       gVesaFramebuffer = (void*)MM_MapHWPages(gVesa_Modes[mode].framebuffer, giVesaPageCount);\r
+       \r
+       LogF(" Vesa_Int_SetMode: Fb (Phys) = 0x%x\n", gVesa_Modes[mode].framebuffer);\r
+       LogF(" Vesa_Int_SetMode: Fb (Virt) = 0x%x\n", gVesaFramebuffer);\r
+       \r
+       // Record Mode Set\r
+       giVesaCurrentMode = mode;\r
+       \r
+       RELEASE( &glVesa_Lock );\r
+       \r
+       return 1;\r
+}\r
+\r
+int Vesa_Int_FindMode(tVideo_IOCtl_Mode *data)\r
+{\r
+        int    i;\r
+        int    best = -1, bestFactor = 1000;\r
+        int    factor, tmp;\r
+       #if DEBUG\r
+       LogF("Vesa_Int_FindMode: (data={width:%i,height:%i,bpp:%i})\n", data->width, data->height, data->bpp);\r
+       #endif\r
+       for(i=0;i<giVesaModeCount;i++)\r
+       {\r
+               #if DEBUG >= 2\r
+               LogF("Mode %i (%ix%ix%i), ", i, gVesa_Modes[i].width, gVesa_Modes[i].height, gVesa_Modes[i].bpp);\r
+               #endif\r
+       \r
+               if(gVesa_Modes[i].width == data->width\r
+               && gVesa_Modes[i].height == data->height\r
+               && gVesa_Modes[i].bpp == data->bpp)\r
+               {\r
+                       #if DEBUG >= 2\r
+                       LogF("Perfect!\n");\r
+                       #endif\r
+                       best = i;\r
+                       break;\r
+               }\r
+               \r
+               tmp = gVesa_Modes[i].width * gVesa_Modes[i].height * gVesa_Modes[i].bpp;\r
+               tmp -= data->width * data->height * data->bpp;\r
+               tmp = tmp < 0 ? -tmp : tmp;\r
+               factor = tmp * 100 / (data->width * data->height * data->bpp);\r
+               \r
+               #if DEBUG >= 2\r
+               LogF("factor = %i\n", factor);\r
+               #endif\r
+               \r
+               if(factor < bestFactor)\r
+               {\r
+                       bestFactor = factor;\r
+                       best = i;\r
+               }\r
+       }\r
+       data->id = best;\r
+       data->width = gVesa_Modes[best].width;\r
+       data->height = gVesa_Modes[best].height;\r
+       data->bpp = gVesa_Modes[best].bpp;\r
+       return best;\r
+}\r
+\r
+int Vesa_Int_ModeInfo(tVideo_IOCtl_Mode *data)\r
+{\r
+       if(data->id < 0 || data->id > giVesaModeCount)  return -1;\r
+       data->width = gVesa_Modes[data->id].width;\r
+       data->height = gVesa_Modes[data->id].height;\r
+       data->bpp = gVesa_Modes[data->id].bpp;\r
+       return 1;\r
+}\r
index 4341bda..9a1b6e8 100644 (file)
@@ -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)
index 80c6d4d..d5c0b3c 100644 (file)
@@ -1 +1,3 @@
+CATEGORY = Network
+
 -include ../../Makefile.tpl
index 9ad8898..a1010a8 100644 (file)
@@ -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 {
index b4f400a..af92731 100644 (file)
@@ -2,6 +2,6 @@
 #
 
 OBJ = main.o uhci.o
-NAME = USB
+NAME = Core
 
 -include ../Makefile.tpl

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