From: John Hodge Date: Sun, 22 Apr 2012 09:36:15 +0000 (+0800) Subject: VESA - Debugging issue on VIA S3 BIOS X-Git-Tag: rel0.15~715 X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=dca6decf0b2d98f521488f071ba3af1a4a6b8647;p=tpg%2Facess2.git VESA - Debugging issue on VIA S3 BIOS --- diff --git a/KernelLand/Kernel/arch/x86/irq.c b/KernelLand/Kernel/arch/x86/irq.c index e2dcf0e3..3d23636e 100644 --- a/KernelLand/Kernel/arch/x86/irq.c +++ b/KernelLand/Kernel/arch/x86/irq.c @@ -26,6 +26,7 @@ void *gaIRQ_DataPointers[16][MAX_CALLBACKS_PER_IRQ]; void IRQ_Handler(tRegs *Regs) { int i, irq = Regs->int_num - 0xF0; + int bHandled = 0; //Log("IRQ_Handler: (Regs={int_num:%i})", Regs->int_num); @@ -37,8 +38,13 @@ void IRQ_Handler(tRegs *Regs) if( irq != 8 ) Log("IRQ %i: Call %p", Regs->int_num, gIRQ_Handlers[Regs->int_num][i]); #endif + bHandled = 1; } } + + if( !bHandled ) { + Log_Debug("IRQ", "Unhandled IRQ %i", irq); + } //Log(" IRQ_Handler: Resetting"); if(irq >= 8) diff --git a/KernelLand/Kernel/arch/x86/vm8086.c b/KernelLand/Kernel/arch/x86/vm8086.c index 61348622..f4e98c4c 100644 --- a/KernelLand/Kernel/arch/x86/vm8086.c +++ b/KernelLand/Kernel/arch/x86/vm8086.c @@ -10,6 +10,8 @@ #include // === CONSTANTS === +#define TRACE_EMU 0 + #define VM8086_MAGIC_CS 0xFFFF #define VM8086_MAGIC_IP 0x0010 #define VM8086_STACK_SEG 0x9F00 @@ -54,6 +56,7 @@ tPID gVM8086_WorkerPID; tTID gVM8086_CallingThread; tVM8086 volatile * volatile gpVM8086_State = (void*)-1; // Set to -1 to avoid race conditions Uint32 gaVM8086_MemBitmap[VM8086_BLOCKCOUNT/32]; + int gbVM8086_ShadowIF = 0; // === FUNCTIONS === int VM8086_Install(char **Arguments) @@ -91,11 +94,11 @@ int VM8086_Install(char **Arguments) MM_Map( 0, 0 ); // IVT / BDA // Map (but allow allocation) of 0x1000 - 0x9F000 // - So much hack, it isn't funny + // TODO: Remove this and replce with something less hacky for(i=1;i<0x9F;i++) { MM_Map( i * 0x1000, i * 0x1000 ); - MM_DerefPhys( i * 0x1000 ); // Above while(MM_GetRefCount(i*0x1000)) - MM_DerefPhys( i * 0x1000 ); // Phys setup + MM_DerefPhys( i * 0x1000 ); } MM_Map( 0x9F000, 0x9F000 ); // Stack / EBDA // System Stack / Stub @@ -165,9 +168,12 @@ int VM8086_Install(char **Arguments) void VM8086_GPF(tRegs *Regs) { Uint8 opcode; + Uint16 newcs, newip; // Log_Log("VM8086", "GPF - %04x:%04x", Regs->cs, Regs->eip); - + + LOG("VM8086 GPF at %04x:%04x", Regs->cs, Regs->eip); + if(Regs->eip == VM8086_MAGIC_IP && Regs->cs == VM8086_MAGIC_CS && Threads_GetPID() == gVM8086_WorkerPID) { @@ -219,17 +225,24 @@ void VM8086_GPF(tRegs *Regs) case VM8086_OP_PUSHF: //PUSHF Regs->esp -= 2; *(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) ) = Regs->eflags & 0xFFFF; + if( gbVM8086_ShadowIF ) + *(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) ) |= 0x200; + else + *(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) ) &= ~0x200; #if TRACE_EMU - Log_Debug("VM8086", "Emulated PUSHF"); + Log_Debug("VM8086", "%04x:%04x Emulated PUSHF (value 0x%x)", + Regs->cs, Regs->eip-1, Regs->eflags & 0xFFFF); #endif break; case VM8086_OP_POPF: //POPF // Changing IF is not allowed Regs->eflags &= 0xFFFF0202; Regs->eflags |= *(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) ); + gbVM8086_ShadowIF = !!(*(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) ) & 0x200); Regs->esp += 2; #if TRACE_EMU - Log_Debug("VM8086", "Emulated POPF"); + Log_Debug("VM8086", "%04x:%04x Emulated POPF (new value 0x%x)", + Regs->cs, Regs->eip-1, Regs->eflags & 0xFFFF); #endif break; @@ -242,20 +255,26 @@ void VM8086_GPF(tRegs *Regs) 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); + newcs = *(Uint16*)(4*id + 2); + newip = *(Uint16*)(4*id); #if TRACE_EMU - Log_Debug("VM8086", "Emulated INT 0x%x", id); + Log_Debug("VM8086", "%04x:%04x Emulated INT 0x%x (%04x:%04x) - AX=%04x,BX=%04x", + Regs->cs, Regs->eip-2, id, newcs, newip, Regs->eax, Regs->ebx); #endif + Regs->cs = newcs; + Regs->eip = newip; } break; case VM8086_OP_IRET: //IRET - Regs->eip = *(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) ); Regs->esp += 2; - Regs->cs = *(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) ); Regs->esp += 2; + newip = *(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) ); Regs->esp += 2; + newcs = *(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) ); Regs->esp += 2; #if TRACE_EMU - Log_Debug("VM8086", "IRET to %04x:%04x", Regs->cs, Regs->eip); + Log_Debug("VM8086", "%04x:%04x IRET to %04x:%04x", + Regs->cs, Regs->eip-1, newcs, newip); #endif + Regs->cs = newcs; + Regs->eip = newip; break; @@ -263,55 +282,72 @@ void VM8086_GPF(tRegs *Regs) Regs->eax &= 0xFFFFFF00; Regs->eax |= inb(Regs->edx&0xFFFF); #if TRACE_EMU - Log_Debug("VM8086", "Emulated IN AL, DX (Port 0x%x)\n", Regs->edx&0xFFFF); + Log_Debug("VM8086", "%04x:%04x Emulated IN AL, DX (Port 0x%x [Val 0x%02x])", + Regs->cs, Regs->eip-1, Regs->edx&0xFFFF, Regs->eax&0xFF); #endif break; case VM8086_OP_IN_ADX: //IN AX, DX Regs->eax &= 0xFFFF0000; Regs->eax |= inw(Regs->edx&0xFFFF); #if TRACE_EMU - Log_Debug("VM8086", "Emulated IN AX, DX (Port 0x%x)\n", Regs->edx&0xFFFF); + Log_Debug("VM8086", "%04x:%04x Emulated IN AX, DX (Port 0x%x [Val 0x%04x])", + Regs->cs, Regs->eip-1, Regs->edx&0xFFFF, Regs->eax&0xFFFF); #endif break; case VM8086_OP_OUT_AD: //OUT DX, AL outb(Regs->edx&0xFFFF, Regs->eax&0xFF); #if TRACE_EMU - Log_Debug("VM8086", "Emulated OUT DX, AL (*0x%04x = 0x%02x)\n", Regs->edx&0xFFFF, Regs->eax&0xFF); + Log_Debug("VM8086", "%04x:%04x Emulated OUT DX, AL (*0x%04x = 0x%02x)", + Regs->cs, Regs->eip-1, Regs->edx&0xFFFF, Regs->eax&0xFF); #endif break; case VM8086_OP_OUT_ADX: //OUT DX, AX outw(Regs->edx&0xFFFF, Regs->eax&0xFFFF); #if TRACE_EMU - Log_Debug("VM8086", "Emulated OUT DX, AX (*0x%04x = 0x%04x)\n", Regs->edx&0xFFFF, Regs->eax&0xFFFF); + Log_Debug("VM8086", "%04x:%04x Emulated OUT DX, AX (*0x%04x = 0x%04x)", + Regs->cs, Regs->eip-1, Regs->edx&0xFFFF, Regs->eax&0xFFFF); #endif break; // TODO: Decide on allowing VM8086 Apps to enable/disable interrupts case 0xFA: //CLI + #if TRACE_EMU + Log_Debug("VM8086", "%04x:%04x Ignored CLI", + Regs->cs, Regs->eip); + #endif + gbVM8086_ShadowIF = 0; break; case 0xFB: //STI + #if TRACE_EMU + Log_Debug("VM8086", "%04x:%04x Ignored STI", + Regs->cs, Regs->eip); + #endif + gbVM8086_ShadowIF = 1; break; case 0x66: opcode = *(Uint8*)( (Regs->cs*16) + (Regs->eip&0xFFFF)); + Regs->eip ++; switch( opcode ) { case VM8086_OP_IN_ADX: //IN AX, DX Regs->eax = ind(Regs->edx&0xFFFF); #if TRACE_EMU - Log_Debug("VM8086", "Emulated IN EAX, DX (Port 0x%x)\n", Regs->edx&0xFFFF); + Log_Debug("VM8086", "%04x:%04x Emulated IN EAX, DX (Port 0x%x [Val 0x%08x])", + Regs->cs, Regs->eip-1, Regs->edx&0xFFFF, Regs->eax); #endif break; case VM8086_OP_OUT_ADX: //OUT DX, AX outd(Regs->edx&0xFFFF, Regs->eax); #if TRACE_EMU - Log_Debug("VM8086", "Emulated OUT DX, EAX (*0x%04x = 0x%08x)\n", Regs->edx&0xFFFF, Regs->eax); + Log_Debug("VM8086", "%04x:%04x Emulated OUT DX, EAX (*0x%04x = 0x%08x)", + Regs->cs, Regs->eip-1, Regs->edx&0xFFFF, Regs->eax); #endif break; default: Log_Error("VM8086", "Error - Unknown opcode 66 %02x caused a GPF at %04x:%04x", - Regs->cs, Regs->eip, + Regs->cs, Regs->eip-2, opcode ); // Force an end to the call @@ -323,7 +359,7 @@ void VM8086_GPF(tRegs *Regs) default: Log_Error("VM8086", "Error - Unknown opcode %02x caused a GPF at %04x:%04x", - opcode, Regs->cs, Regs->eip); + opcode, Regs->cs, Regs->eip-1); // Force an end to the call Regs->cs = VM8086_MAGIC_CS; Regs->eip = VM8086_MAGIC_IP; diff --git a/KernelLand/Kernel/debug.c b/KernelLand/Kernel/debug.c index 9edf1264..6a50ca2c 100644 --- a/KernelLand/Kernel/debug.c +++ b/KernelLand/Kernel/debug.c @@ -1,17 +1,13 @@ /* * AcessOS Microkernel Version * debug.c - * - * TODO: Move the Debug_putchar methods out to the arch/ tree */ #include #include #define DEBUG_MAX_LINE_LEN 256 - -#define LOCK_DEBUG_OUTPUT 1 - -#define TRACE_TO_KTERM 1 +#define LOCK_DEBUG_OUTPUT 1 // Avoid interleaving of output lines? +#define TRACE_TO_KTERM 0 // Send ENTER/DEBUG/LEAVE to debug? // === IMPORTS === extern void Threads_Dump(void); diff --git a/KernelLand/Kernel/drv/vterm.c b/KernelLand/Kernel/drv/vterm.c index 5f4a25ca..1cc60bec 100644 --- a/KernelLand/Kernel/drv/vterm.c +++ b/KernelLand/Kernel/drv/vterm.c @@ -758,6 +758,8 @@ void VT_SetTerminal(int ID) giVT_CurrentTerminal = ID; gpVT_CurTerm = &gVT_Terminals[ID]; + LOG("Attempting VT_SetMode"); + if( gpVT_CurTerm->Mode == TERM_MODE_TEXT ) { VT_SetMode( VIDEO_BUFFMT_TEXT ); @@ -769,7 +771,9 @@ void VT_SetTerminal(int ID) VFS_IOCtl(giVT_OutputDevHandle, VIDEO_IOCTL_SETCURSORBITMAP, gpVT_CurTerm->VideoCursor); VT_SetMode( VIDEO_BUFFMT_FRAMEBUFFER ); } - + + LOG("Mode set"); + if(gpVT_CurTerm->Buffer) { // TODO: Handle non equal sized @@ -779,9 +783,11 @@ void VT_SetTerminal(int ID) gpVT_CurTerm->Width*gpVT_CurTerm->Height*sizeof(Uint32), gpVT_CurTerm->Buffer ); + LOG("Updated screen contents"); } VT_int_UpdateCursor(gpVT_CurTerm, 1); // Update the screen VT_int_UpdateScreen(gpVT_CurTerm, 1); + LOG("done"); } diff --git a/KernelLand/Kernel/drv/vterm_output.c b/KernelLand/Kernel/drv/vterm_output.c index 4d1c352b..357132c0 100644 --- a/KernelLand/Kernel/drv/vterm_output.c +++ b/KernelLand/Kernel/drv/vterm_output.c @@ -7,7 +7,7 @@ */ #include "vterm.h" #include -#define DEBUG 1 +#define DEBUG 0 // === CODE === /** diff --git a/KernelLand/Kernel/drvutil.c b/KernelLand/Kernel/drvutil.c index d9bd92df..d2c86bfb 100644 --- a/KernelLand/Kernel/drvutil.c +++ b/KernelLand/Kernel/drvutil.c @@ -136,7 +136,7 @@ int DrvUtil_Video_WriteLFB(tDrvUtil_Video_BufInfo *FBInfo, size_t Offset, size_t int x, y; int bytes_per_px = (FBInfo->Depth + 7) / 8; ENTER("pFBInfo xOffset xLength pBuffer", - Mode, FBInfo, Offset, Length, Buffer); + FBInfo, Offset, Length, Buffer); csr_x = FBInfo->CursorX; csr_y = FBInfo->CursorY; @@ -287,9 +287,12 @@ int DrvUtil_Video_SetCursor(tDrvUtil_Video_BufInfo *Buf, tVideo_IOCtl_Bitmap *Bi int csrX = Buf->CursorX, csrY = Buf->CursorY; size_t size; + ENTER("pBuf pBitmap", Buf, Bitmap); + // Clear old bitmap if( Buf->CursorBitmap ) { + LOG("Clearing old cursor"); DrvUtil_Video_RemoveCursor(Buf); if( !Bitmap || Bitmap->W != Buf->CursorBitmap->W || Bitmap->H != Buf->CursorBitmap->H ) { @@ -306,24 +309,29 @@ int DrvUtil_Video_SetCursor(tDrvUtil_Video_BufInfo *Buf, tVideo_IOCtl_Bitmap *Bi { Buf->CursorX = -1; Buf->CursorY = -1; + LEAVE('i', 0); return 0; } // Sanity check the bitmap + LOG("Sanity checking plox"); if( !CheckMem(Bitmap, sizeof(*Bitmap)) || !CheckMem(Bitmap->Data, Bitmap->W*Bitmap->H*sizeof(Uint32)) ) { Log_Warning("DrvUtil", "DrvUtil_Video_SetCursor: Bitmap (%p) is in invalid memory", Bitmap); errno = -EINVAL; + LEAVE('i', -1); return -1; } // Don't take a copy of the DrvUtil provided cursor if( Bitmap == &gDrvUtil_TextModeCursor ) { + LOG("No copy (provided cursor)"); Buf->CursorBitmap = Bitmap; } else { + LOG("Make copy"); size = sizeof(tVideo_IOCtl_Bitmap) + Bitmap->W*Bitmap->H*4; // Take a copy @@ -332,7 +340,9 @@ int DrvUtil_Video_SetCursor(tDrvUtil_Video_BufInfo *Buf, tVideo_IOCtl_Bitmap *Bi } // Restore cursor position + LOG("Drawing"); DrvUtil_Video_DrawCursor(Buf, csrX, csrY); + LEAVE('i', 0); return 0; } @@ -340,24 +350,30 @@ void DrvUtil_Video_DrawCursor(tDrvUtil_Video_BufInfo *Buf, int X, int Y) { int render_ox=0, render_oy=0, render_w, render_h; + ENTER("pBuf iX iY", Buf, X, Y); DrvUtil_Video_RemoveCursor(Buf); // X < 0 disables the cursor if( X < 0 ) { Buf->CursorX = -1; + LEAVE('-'); return ; } // Sanity checking - if( X < 0 || Y < 0 ) return; - if( X >= Buf->Width || Y >= Buf->Height ) return; + if( X < 0 || Y < 0 || X >= Buf->Width || Y >= Buf->Height ) { + LEAVE('-'); + return ; + } // Ensure the cursor is enabled - if( !Buf->CursorBitmap ) return ; + if( !Buf->CursorBitmap ) { + LEAVE('-'); + return ; + } // Save cursor position (for changing the bitmap) Buf->CursorX = X; Buf->CursorY = Y; - // Apply cursor's center offset X -= Buf->CursorBitmap->XOfs; Y -= Buf->CursorBitmap->YOfs; @@ -375,8 +391,12 @@ void DrvUtil_Video_DrawCursor(tDrvUtil_Video_BufInfo *Buf, int X, int Y) Buf->CursorDestX = X; Buf->CursorDestY = Y; Buf->CursorReadX = render_ox; Buf->CursorReadY = render_oy; + LOG("%ix%i at %i,%i offset %i,%i", + render_w, render_h, X, Y, render_ox, render_oy); + // Call render routine DrvUtil_Video_RenderCursor(Buf); + LEAVE('-'); } void DrvUtil_Video_RenderCursor(tDrvUtil_Video_BufInfo *Buf) @@ -393,10 +413,13 @@ void DrvUtil_Video_RenderCursor(tDrvUtil_Video_BufInfo *Buf) dest = (Uint8*)Buf->Framebuffer + dest_y*Buf->Pitch + dest_x*bytes_per_px; src = Buf->CursorBitmap->Data + src_y * Buf->CursorBitmap->W + src_x; + LOG("dest = %p, src = %p", dest, src); + // Allocate save buffer if not already if( !Buf->CursorSaveBuf ) Buf->CursorSaveBuf = malloc( Buf->CursorBitmap->W*Buf->CursorBitmap->H*bytes_per_px ); + LOG("Saving back"); // Save behind the cursor for( y = 0; y < render_h; y ++ ) memcpy( @@ -413,6 +436,7 @@ void DrvUtil_Video_RenderCursor(tDrvUtil_Video_BufInfo *Buf) Log_Warning("DrvUtil", "TODO: Support 15/16 bpp modes in cursor draw"); break; case 24: + LOG("24-bit render"); for( y = 0; y < render_h; y ++ ) { Uint8 *px; @@ -435,6 +459,7 @@ void DrvUtil_Video_RenderCursor(tDrvUtil_Video_BufInfo *Buf) } break; case 32: + LOG("32-bit render"); for( y = 0; y < render_h; y ++ ) { Uint32 *px; @@ -448,6 +473,7 @@ void DrvUtil_Video_RenderCursor(tDrvUtil_Video_BufInfo *Buf) else ; // NOP, completely transparent } + LOG("row %i/%i (%p-%P) done", y+1, render_h, dest, MM_GetPhysAddr(dest)); src += Buf->CursorBitmap->W; dest = (Uint8*)dest + Buf->Pitch; } diff --git a/KernelLand/Modules/Display/VESA/common.h b/KernelLand/Modules/Display/VESA/common.h index eeaddd56..c81fe1a8 100644 --- a/KernelLand/Modules/Display/VESA/common.h +++ b/KernelLand/Modules/Display/VESA/common.h @@ -22,7 +22,24 @@ typedef struct sVesa_Mode typedef struct sVesa_CallModeInfo { + /** + * 0 : Mode is supported + * 1 : Optional information avaliable (Xres onwards) + * 2 : BIOS Output Supported + * 3 : Colour Mode? + * 4 : Graphics mode? + * -- VBE v2.0+ + * 5 : Mode is not VGA compatible + * 6 : Bank switched mode supported + * 7 : Linear framebuffer mode supported + * 8 : Double-scan mode avaliable + */ Uint16 attributes; + /** + * 0 : Window exists + * 1 : Window is readable + * 2 : Window is writable + */ Uint8 winA,winB; Uint16 granularity; Uint16 winsize; @@ -35,25 +52,32 @@ typedef struct sVesa_CallModeInfo Uint8 memory_model, bank_size, image_pages; Uint8 reserved0; + // -- VBE v1.2+ 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; + // -- VBE v2.0+ + Uint32 physbase; + Uint32 offscreen_ptr; // Start of offscreen memory + Uint16 offscreen_size_kb; // Size of offscreen memory + + // -- VBE v3.0 + Uint16 lfb_pitch; + Uint8 image_count_banked; + Uint8 image_count_lfb; } 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 + 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/KernelLand/Modules/Display/VESA/main.c b/KernelLand/Modules/Display/VESA/main.c index 2dbc98ce..c9e3c84d 100644 --- a/KernelLand/Modules/Display/VESA/main.c +++ b/KernelLand/Modules/Display/VESA/main.c @@ -16,6 +16,8 @@ // === CONSTANTS === #define FLAG_LFB 0x1 +#define FLAG_POPULATED 0x2 +#define FLAG_VALID 0x4 #define VESA_DEFAULT_FRAMEBUFFER (KERNEL_BASE|0xA0000) #define BLINKING_CURSOR 1 #if BLINKING_CURSOR @@ -24,6 +26,7 @@ // === PROTOTYPES === int Vesa_Install(char **Arguments); + int VBE_int_GetModeList(void); size_t Vesa_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer); int Vesa_IOCtl(tVFS_Node *Node, int ID, void *Data); int Vesa_Int_SetMode(int Mode); @@ -67,6 +70,27 @@ tDrvUtil_Video_BufInfo gVesa_BufInfo; // === CODE === int Vesa_Install(char **Arguments) +{ + int rv; + + gpVesa_BiosState = VM8086_Init(); + + if( (rv = VBE_int_GetModeList()) ) + return rv; + + #if BLINKING_CURSOR + // Create blink timer + gpVesaCursorTimer = Time_AllocateTimer( Vesa_FlipCursor, NULL ); + #endif + + // Install Device + giVesaDriverId = DevFS_AddDevice( &gVesa_DriverStruct ); + if(giVesaDriverId == -1) return MODULE_ERR_MISC; + + return MODULE_ERR_OK; +} + +int VBE_int_GetModeList(void) { tVesa_CallInfo *info; tFarPtr infoPtr; @@ -74,7 +98,6 @@ int Vesa_Install(char **Arguments) int i; // Allocate Info Block - gpVesa_BiosState = VM8086_Init(); info = VM8086_Allocate(gpVesa_BiosState, 512, &infoPtr.seg, &infoPtr.ofs); // Set Requested Version memcpy(info->signature, "VBE2", 4); @@ -88,15 +111,16 @@ int Vesa_Install(char **Arguments) return MODULE_ERR_NOTNEEDED; } - //Log_Debug("VESA", "info->VideoModes = %04x:%04x", info->VideoModes.seg, info->VideoModes.ofs); modes = (Uint16 *) VM8086_GetPointer(gpVesa_BiosState, info->VideoModes.seg, info->VideoModes.ofs); +// VM8086_Deallocate( gpVesa_BiosState, info ); - // Read Modes + // Count Modes for( giVesaModeCount = 0; modes[giVesaModeCount] != 0xFFFF; giVesaModeCount++ ); + giVesaModeCount ++; // First text mode gVesa_Modes = (tVesa_Mode *)malloc( giVesaModeCount * sizeof(tVesa_Mode) ); - Log_Debug("VESA", "%i Modes", giVesaModeCount); - + Log_Debug("VBE", "%i Modes", giVesaModeCount); + // Insert Text Mode gVesa_Modes[0].width = 80; gVesa_Modes[0].height = 25; @@ -108,22 +132,103 @@ int Vesa_Install(char **Arguments) for( i = 1; i < giVesaModeCount; i++ ) { - gVesa_Modes[i].code = modes[i]; + gVesa_Modes[i].code = modes[i-1]; } - -// VM8086_Deallocate( info ); - #if BLINKING_CURSOR - // Create blink timer - gpVesaCursorTimer = Time_AllocateTimer( Vesa_FlipCursor, NULL ); + return 0; +} + +void VBE_int_FillMode_Int(int Index, tVesa_CallModeInfo *vbeinfo, tFarPtr *BufPtr) +{ + tVesa_Mode *mode = &gVesa_Modes[Index]; + + // Get Mode info + gpVesa_BiosState->AX = 0x4F01; + gpVesa_BiosState->CX = mode->code; + gpVesa_BiosState->ES = BufPtr->seg; + gpVesa_BiosState->DI = BufPtr->ofs; + VM8086_Int(gpVesa_BiosState, 0x10); + + if( gpVesa_BiosState->AX != 0x004F ) { + Log_Error("VESA", "Getting info on mode 0x%x failed (AX=0x%x)", + mode->code, gpVesa_BiosState->AX); + return ; + } + + #define S_LOG(s, fld, fmt) LOG(" ."#fld" = "fmt, (s).fld) + LOG("vbeinfo[0x%x] = {", mode->code); + S_LOG(*vbeinfo, attributes, "0x%02x"); + S_LOG(*vbeinfo, winA, "0x%02x"); + S_LOG(*vbeinfo, winB, "0x%02x"); + S_LOG(*vbeinfo, granularity, "0x%04x"); + S_LOG(*vbeinfo, winsize, "0x%04x"); + S_LOG(*vbeinfo, segmentA, "0x%04x"); + S_LOG(*vbeinfo, segmentB, "0x%04x"); + LOG(" .realFctPtr = %04x:%04x", vbeinfo->realFctPtr.seg, vbeinfo->realFctPtr.ofs); + S_LOG(*vbeinfo, pitch, "0x%04x"); + // -- Extended + S_LOG(*vbeinfo, Xres, "%i"); + S_LOG(*vbeinfo, Yres, "%i"); + S_LOG(*vbeinfo, Wchar, "%i"); + S_LOG(*vbeinfo, Ychar, "%i"); + S_LOG(*vbeinfo, planes, "%i"); + S_LOG(*vbeinfo, bpp, "%i"); + S_LOG(*vbeinfo, banks, "%i"); + S_LOG(*vbeinfo, memory_model, "%i"); + S_LOG(*vbeinfo, bank_size, "%i"); + S_LOG(*vbeinfo, image_pages, "%i"); + // -- VBE 1.2+ + LOG(" Red = %i bits at %i", vbeinfo->red_mask, vbeinfo->red_position ); + LOG(" Green = %i bits at %i", vbeinfo->green_mask, vbeinfo->green_position); + LOG(" Blue = %i bits at %i", vbeinfo->blue_mask, vbeinfo->blue_position ); + #if 0 + Uint8 rsv_mask, rsv_position; + Uint8 directcolor_attributes; #endif + // --- VBE 2.0+ + S_LOG(*vbeinfo, physbase, "0x%08x"); + S_LOG(*vbeinfo, offscreen_ptr, "0x%08x"); + S_LOG(*vbeinfo, offscreen_size_kb, "0x%04x"); + // --- VBE 3.0+ + S_LOG(*vbeinfo, lfb_pitch, "0x%04x"); + S_LOG(*vbeinfo, image_count_banked, "%i"); + S_LOG(*vbeinfo, image_count_lfb, "%i"); + LOG("}"); - // Install Device - giVesaDriverId = DevFS_AddDevice( &gVesa_DriverStruct ); - if(giVesaDriverId == -1) return MODULE_ERR_MISC; + mode->flags = FLAG_POPULATED; + if( !(vbeinfo->attributes & 1) ) { + #if DEBUG + Log_Log("VESA", "0x%x - not supported", mode->code); + #endif + mode->width = 0; + mode->height = 0; + mode->bpp = 0; + return ; + } - return MODULE_ERR_OK; -} + // Parse Info + mode->flags |= FLAG_VALID; + if ( (vbeinfo->attributes & 0x90) == 0x90 ) + { + mode->flags |= FLAG_LFB; + mode->framebuffer = vbeinfo->physbase; + mode->fbSize = vbeinfo->Yres*vbeinfo->pitch; + } else { + mode->framebuffer = 0; + mode->fbSize = 0; + } + + mode->pitch = vbeinfo->pitch; + mode->width = vbeinfo->Xres; + mode->height = vbeinfo->Yres; + mode->bpp = vbeinfo->bpp; + + #if DEBUG + Log_Log("VESA", "#%i 0x%x - %ix%ix%i (%x)", + Index, mode->code, mode->width, mode->height, mode->bpp, mode->flags); + #endif + +} void Vesa_int_FillModeList(void) { @@ -133,40 +238,12 @@ void Vesa_int_FillModeList(void) tVesa_CallModeInfo *modeinfo; tFarPtr modeinfoPtr; - modeinfo = VM8086_Allocate(gpVesa_BiosState, 512, &modeinfoPtr.seg, &modeinfoPtr.ofs); + modeinfo = VM8086_Allocate(gpVesa_BiosState, 256, &modeinfoPtr.seg, &modeinfoPtr.ofs); for( i = 1; i < giVesaModeCount; 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->Yres*modeinfo->pitch; - } else { - gVesa_Modes[i].framebuffer = 0; - gVesa_Modes[i].fbSize = 0; - } - - gVesa_Modes[i].pitch = modeinfo->pitch; - gVesa_Modes[i].width = modeinfo->Xres; - gVesa_Modes[i].height = modeinfo->Yres; - gVesa_Modes[i].bpp = modeinfo->bpp; - - #if DEBUG - Log_Log("VESA", "0x%x - %ix%ix%i", - gVesa_Modes[i].code, gVesa_Modes[i].width, gVesa_Modes[i].height, gVesa_Modes[i].bpp); - #endif - } - -// VM8086_Deallocate( modeinfo ); + VBE_int_FillMode_Int(i, modeinfo, &modeinfoPtr); + } +// VM8086_Deallocate( gpVesa_BiosState, modeinfo ); gbVesaModesChecked = 1; } @@ -192,7 +269,6 @@ const char *csaVESA_IOCtls[] = {DRV_IOCTLNAMES, DRV_VIDEO_IOCTLNAMES, NULL}; int Vesa_IOCtl(tVFS_Node *Node, int ID, void *Data) { int ret; - //Log_Debug("VESA", "Vesa_Ioctl: (Node=%p, ID=%i, Data=%p)", Node, ID, Data); switch(ID) { BASE_IOCTLS(DRV_TYPE_VIDEO, "VESA", VERSION, csaVESA_IOCtls); @@ -207,11 +283,15 @@ int Vesa_IOCtl(tVFS_Node *Node, int ID, void *Data) return Vesa_Int_ModeInfo((tVideo_IOCtl_Mode*)Data); case VIDEO_IOCTL_SETBUFFORMAT: + LOG("Hide cursor"); Vesa_int_HideCursor(); + LOG("Update internals"); ret = gVesa_BufInfo.BufferFormat; if(Data) gVesa_BufInfo.BufferFormat = *(int*)Data; + LOG("Swap back to text mode cursor"); if(gVesa_BufInfo.BufferFormat == VIDEO_BUFFMT_TEXT) DrvUtil_Video_SetCursor( &gVesa_BufInfo, &gDrvUtil_TextModeCursor ); + LOG("Show again"); Vesa_int_ShowCursor(); return ret; @@ -249,11 +329,15 @@ int Vesa_Int_SetMode(int mode) gpVesa_BiosState->AX = 0x4F02; gpVesa_BiosState->BX = gVesa_Modes[mode].code; if(gVesa_Modes[mode].flags & FLAG_LFB) { - gpVesa_BiosState->BX |= 0x4000; // Bit 14 - Use LFB + gpVesa_BiosState->BX |= 1 << 14; // Use LFB } + LOG("In : AX=%04x/BX=%04x", + gpVesa_BiosState->AX, gpVesa_BiosState->BX); // Set Mode VM8086_Int(gpVesa_BiosState, 0x10); + + LOG("Out: AX = %04x", gpVesa_BiosState->AX); // Map Framebuffer if( (tVAddr)gpVesa_Framebuffer != VESA_DEFAULT_FRAMEBUFFER ) @@ -261,8 +345,8 @@ int Vesa_Int_SetMode(int mode) giVesaPageCount = (gVesa_Modes[mode].fbSize + 0xFFF) >> 12; gpVesa_Framebuffer = (void*)MM_MapHWPages(gVesa_Modes[mode].framebuffer, giVesaPageCount); - Log_Log("VESA", "Setting mode to %i (%ix%i %ibpp) %p[0x%x] maps %P", - mode, + Log_Log("VESA", "Setting mode to %i 0x%x (%ix%i %ibpp) %p[0x%x] maps %P", + mode, gVesa_Modes[mode].code, gVesa_Modes[mode].width, gVesa_Modes[mode].height, gVesa_Modes[mode].bpp, gpVesa_Framebuffer, giVesaPageCount << 12, gVesa_Modes[mode].framebuffer