-BUILD_NUM = 1636
+BUILD_NUM = 1696
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
// === IMPORTS ===
extern void MM_PageFault(Uint Addr, Uint ErrorCode, tRegs *Regs);
+extern void VM8086_GPF(tRegs *Regs);
extern void Threads_Dump();
// === PROTOTYPES ===
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));
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);
#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
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;
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
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 )
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
gaPageReferences[idx*32+sidx] = 1;
gaPageBitmap[ idx ] |= 1 << sidx;
sidx ++;
- if(sidx == 32) { sidx = 0; idx ++; }
+ if(sidx == 32) { sidx = 0; idx ++; }
}
// Get address
// Release Spinlock
RELEASE( &giPhysAlloc );
+ LEAVE('X', ret);
return ret;
}
}
/**
- * \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;
{
phys = MM_AllocPhys();
*PhysAddr = phys;
- ret = MM_MapHWPage(phys, 1);
+ ret = MM_MapHWPages(phys, 1);
if(ret == 0) {
MM_DerefPhys(phys);
LEAVE('i', 0);
}
// 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)
}
/**
- * \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
EXPORT(MM_GetPhysAddr);
EXPORT(MM_Map);
//EXPORT(MM_Unmap);
-EXPORT(MM_MapHWPage);
+EXPORT(MM_MapHWPages);
EXPORT(MM_AllocDMA);
-EXPORT(MM_UnmapHWPage);
+EXPORT(MM_UnmapHWPages);
// === CONSTANTS ===
#define SWITCH_MAGIC 0xFFFACE55 // There is no code in this area
+// Base is 1193182
#define TIMER_DIVISOR 11931 //~100Hz
// === IMPORTS ===
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 ===
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
*--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
--- /dev/null
+/*
+ * 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 );
+}
\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
// === CONSTANTS ===
#define KB_BUFFER_SIZE 1024
+#define USE_KERNEL_MAGIC 1
// === IMPORTS ===
void Threads_Dump();
//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);
// --- 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)
* \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
* \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
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);
/**
* \}
*/
// --- 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
// === 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);
* \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;
}
/**
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 );
// 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");
}
{
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;
}
}
+void Threads_WakeTID(tTID Thread)
+{
+ Threads_Wake( Threads_GetThread(Thread) );
+}
+
/**
* \fn void Threads_AddActive(tThread *Thread)
* \brief Adds a thread to the active queue
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;
}
giTotalTickets, number);
}
+ //Log_Debug("Threads", "Switching CPU%i to %p (%s)",
+ // CPU, thread, thread->ThreadName);
+
return thread;
}
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-%:
@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
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
--- /dev/null
+#
+#
+
+OBJ = main.o
+NAME = VESA
+
+-include ../Makefile.tpl
--- /dev/null
+/**
+ */
+#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
--- /dev/null
+/*\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
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)
+CATEGORY = Network
+
-include ../../Makefile.tpl
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 {
#
OBJ = main.o uhci.o
-NAME = USB
+NAME = Core
-include ../Makefile.tpl