diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..acfaa18 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +.vscode/ +res/*.obj +res/*.bin +*.obj +*.err +*.lib +*.drv +*.map +*.res +*.img \ No newline at end of file diff --git a/boxv.c b/boxv.c index e52cd79..1a4dd2e 100644 --- a/boxv.c +++ b/boxv.c @@ -81,7 +81,7 @@ int BOXV_ext_mode_set( void *cx, int xres, int yres, int bpp, int v_xres, int v_ vid_outw( cx, VBE_DISPI_IOPORT_DATA, 0 ); /* Enable the extended display registers. */ vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ENABLE ); - vid_outw( cx, VBE_DISPI_IOPORT_DATA, VBE_DISPI_ENABLED | VBE_DISPI_8BIT_DAC ); + vid_outw( cx, VBE_DISPI_IOPORT_DATA, VBE_DISPI_ENABLED | VBE_DISPI_8BIT_DAC | VBE_DISPI_LFB_ENABLED ); /* Re-enable the sequencer. */ vid_wridx( cx, VGA_SEQUENCER, VGA_SR_RESET, VGA_SR0_NORESET ); @@ -126,13 +126,16 @@ int BOXV_detect( void *cx, unsigned long *vram_size ) vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID ); boxv_id = vid_inw( cx, VBE_DISPI_IOPORT_DATA ); + + if( boxv_id < VBE_DISPI_ID0 || boxv_id > VBE_DISPI_ID6 ) + return( 0 ); + if( vram_size ) { - *vram_size = vid_ind( cx, VBE_DISPI_IOPORT_DATA ); + vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_VIDEO_MEMORY_64K ); + *vram_size = (unsigned long)vid_inw( cx, VBE_DISPI_IOPORT_DATA ) << 16; } - if( boxv_id >= VBE_DISPI_ID0 && boxv_id <= VBE_DISPI_ID4 ) - return( boxv_id ); - else - return( 0 ); + + return( boxv_id ); } /* Disable extended mode and place the hardware into a VGA compatible state. @@ -145,25 +148,3 @@ int BOXV_ext_disable( void *cx ) vid_outw( cx, VBE_DISPI_IOPORT_DATA, VBE_DISPI_DISABLED ); return( 0 ); } - -/* Return the physical base address of the framebuffer. Needed in environments - * that do not query the base through PCI. - */ -unsigned long BOXV_get_lfb_base( void *cx ) -{ - unsigned long fb_base; - - /* Ask the virtual hardware for the high 16 bits. */ - vid_outw( cx, VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_FB_BASE_HI ); - fb_base = vid_inw( cx, VBE_DISPI_IOPORT_DATA ); - - /* Old versions didn't support that, so use the default - * if the value looks like garbage. - */ - if( fb_base != 0 && fb_base != 0xffff ) - fb_base = fb_base << 16; - else - fb_base = VBE_DISPI_LFB_PHYSICAL_ADDRESS; - - return( fb_base ); -} diff --git a/boxv.h b/boxv.h index 8d32213..6b6dfef 100644 --- a/boxv.h +++ b/boxv.h @@ -46,4 +46,3 @@ extern int BOXV_ext_mode_set( void *cx, int xres, int yres, int bpp, int v_xres extern int BOXV_mode_set( void *cx, int mode_no ); extern int BOXV_dac_set( void *cx, unsigned start, unsigned count, void *pal ); extern int BOXV_ext_disable( void *cx ); -extern unsigned long BOXV_get_lfb_base( void *cx ); diff --git a/boxv_io.h b/boxv_io.h index fc05466..dbb4f65 100644 --- a/boxv_io.h +++ b/boxv_io.h @@ -60,8 +60,3 @@ static unsigned vid_inw( void *cx, unsigned port ) { return( inpw( port ) ); } - -static unsigned long vid_ind( void *cx, unsigned port ) -{ - return( inpd( port ) ); -} diff --git a/boxvint.h b/boxvint.h index 6ec2bf3..401976b 100644 --- a/boxvint.h +++ b/boxvint.h @@ -94,34 +94,32 @@ THE SOFTWARE. #define VBE_DISPI_IOPORT_INDEX 0x01CE #define VBE_DISPI_IOPORT_DATA 0x01CF -#define VBE_DISPI_INDEX_ID 0x0 -#define VBE_DISPI_INDEX_XRES 0x1 -#define VBE_DISPI_INDEX_YRES 0x2 -#define VBE_DISPI_INDEX_BPP 0x3 -#define VBE_DISPI_INDEX_ENABLE 0x4 -#define VBE_DISPI_INDEX_BANK 0x5 -#define VBE_DISPI_INDEX_VIRT_WIDTH 0x6 -#define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7 -#define VBE_DISPI_INDEX_X_OFFSET 0x8 -#define VBE_DISPI_INDEX_Y_OFFSET 0x9 -#define VBE_DISPI_INDEX_VBOX_VIDEO 0xa -#define VBE_DISPI_INDEX_FB_BASE_HI 0xb - -#define VBE_DISPI_ID0 0xB0C0 -#define VBE_DISPI_ID1 0xB0C1 -#define VBE_DISPI_ID2 0xB0C2 -#define VBE_DISPI_ID3 0xB0C3 -#define VBE_DISPI_ID4 0xB0C4 - -#define VBE_DISPI_DISABLED 0x00 -#define VBE_DISPI_ENABLED 0x01 -#define VBE_DISPI_GETCAPS 0x02 -#define VBE_DISPI_8BIT_DAC 0x20 -#define VBE_DISPI_LFB_ENABLED 0x40 -#define VBE_DISPI_NOCLEARMEM 0x80 - -/* Default LFB base. Might be different! */ -#define VBE_DISPI_LFB_PHYSICAL_ADDRESS 0xE0000000 +#define VBE_DISPI_INDEX_ID 0x0 +#define VBE_DISPI_INDEX_XRES 0x1 +#define VBE_DISPI_INDEX_YRES 0x2 +#define VBE_DISPI_INDEX_BPP 0x3 +#define VBE_DISPI_INDEX_ENABLE 0x4 +#define VBE_DISPI_INDEX_BANK 0x5 +#define VBE_DISPI_INDEX_VIRT_WIDTH 0x6 +#define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7 +#define VBE_DISPI_INDEX_X_OFFSET 0x8 +#define VBE_DISPI_INDEX_Y_OFFSET 0x9 +#define VBE_DISPI_INDEX_VIDEO_MEMORY_64K 0xa + +#define VBE_DISPI_ID0 0xB0C0 +#define VBE_DISPI_ID1 0xB0C1 +#define VBE_DISPI_ID2 0xB0C2 +#define VBE_DISPI_ID3 0xB0C3 +#define VBE_DISPI_ID4 0xB0C4 +#define VBE_DISPI_ID5 0xB0C5 +#define VBE_DISPI_ID6 0xB0C6 + +#define VBE_DISPI_DISABLED 0x00 +#define VBE_DISPI_ENABLED 0x01 +#define VBE_DISPI_GETCAPS 0x02 +#define VBE_DISPI_8BIT_DAC 0x20 +#define VBE_DISPI_LFB_ENABLED 0x40 +#define VBE_DISPI_NOCLEARMEM 0x80 /*------------ End bochs Specific -------------*/ diff --git a/dbgprint.c b/dbgprint.c index dde0c42..fed6429 100644 --- a/dbgprint.c +++ b/dbgprint.c @@ -35,8 +35,7 @@ THE SOFTWARE. /* Backdoor logging I/O ports. */ -#define INFO_PORT 0x504 -#define DEBUG_PORT 0x403 +#define INFO_PORT 0xe9 #pragma code_seg( _INIT ); diff --git a/ddk/configmg.h b/ddk/configmg.h new file mode 100644 index 0000000..d11b4f3 --- /dev/null +++ b/ddk/configmg.h @@ -0,0 +1,32 @@ + +/* Definitions for the configuration manager. */ + +typedef DWORD CONFIGRET; /* Standardized return value. */ + +typedef DWORD LOG_CONF; /* Logical configuration. */ +typedef LOG_CONF FAR *PLOG_CONF; /* Far pointer to logical configuration. */ + +typedef DWORD RES_DES; /* Resource descriptor. */ +typedef RES_DES FAR *PRES_DES; /* Far pointer to resource descriptor. */ + +typedef DWORD DEVNODE; /* Devnode. */ + +typedef DWORD ULONG; + +typedef void FAR *PFARVOID; + +typedef ULONG RESOURCEID; /* Resource type ID. */ +typedef RESOURCEID FAR *PRESOURCEID; /* Far pointer to resource type ID. */ + +typedef struct { + WORD MD_Count; + WORD MD_Type; + ULONG MD_Alloc_Base; + ULONG MD_Alloc_End; + WORD MD_Flags; + WORD MD_Reserved; +} MEM_DES, *PMEM_DES; + +#define CR_SUCCESS 0 +#define ALLOC_LOG_CONF 2 +#define ResType_Mem 1 diff --git a/init.c b/init.c index 8fa0638..b8df3d0 100644 --- a/init.c +++ b/init.c @@ -29,7 +29,7 @@ THE SOFTWARE. #include #include #include "minidrv.h" - +#include /* GlobalSmartPageLock is a semi-undocumented function. Not officially * documented but described in KB Article Q180586. */ @@ -41,8 +41,10 @@ WORD wDpi = 96; /* Current DPI setting. */ WORD wBpp = 8; /* Current BPP setting. */ WORD wPalettized = 0; /* Non-zero if palettized. */ -WORD OurVMHandle = 0; /* The current VM's ID. */ -DWORD VDDEntryPoint = 0; /* The VDD entry point. */ +WORD OurVMHandle = 0; /* The current VM's ID. */ +DWORD VDDEntryPoint = 0; /* The VDD entry point. */ +DWORD ConfigMGEntryPoint = 0; /* The configuration manager entry point. */ +DWORD LfbBase = 0; /* The physical base address of the linear framebuffer. */ /* On Entry: * EAX = Function code (VDD_GET_DISPLAY_CONFIG) @@ -65,18 +67,72 @@ extern DWORD CallVDDGetDispConf( WORD Function, WORD wDInfSize, LPVOID pDInf ); "call dword ptr VDDEntryPoint"\ "mov edx, eax" \ "shr edx, 16" \ - parm [ax] [cx] [es di]; + parm [ax] [cx] [es di] modify [bx]; #pragma code_seg( _INIT ) +/* Get the first logical configuration for a devnode. + */ +CONFIGRET static _near _cdecl CM_Get_First_Log_Conf( + PLOG_CONF plcLogConf, + DEVNODE dnDevNode, + ULONG ulFlags) +{ + WORD wRc = 0; + + _asm { mov eax, 01Ah }; /* CM_GET_FIRST_LOG_CONF */ + _asm { call ConfigMGEntryPoint }; + _asm { mov wRc, ax }; + + return( wRc ); +} + +/* Get the next resource descriptor of a given type. + */ +CONFIGRET static _near _cdecl CM_Get_Next_Res_Des( + PRES_DES prdResDes, + RES_DES CurrentResDesOrLogConf, + RESOURCEID ForResource, + PRESOURCEID pResourceID, + ULONG ulFlags) +{ + WORD wRc = 0; + + _asm { mov eax, 01Fh }; /* CM_GET_NEXT_RES_DES */ + _asm { call ConfigMGEntryPoint }; + _asm { mov wRc, ax }; + + return( wRc ); +} + +/* Get the data for a resource descriptor. + */ +CONFIGRET static _near _cdecl CM_Get_Res_Des_Data( + RES_DES rdResDes, + PFARVOID Buffer, + ULONG BufferLen, + ULONG ulFlags) +{ + WORD wRc = 0; + + _asm { mov eax, 022h }; /* CM_GET_RES_DES_DATA */ + _asm { call ConfigMGEntryPoint }; + _asm { mov wRc, ax }; + + return( wRc ); +} + /* Read the display settings from SYSTEM.INI or Registry. */ -void ReadDisplayConfig( void ) +DEVNODE ReadDisplayConfig( void ) { WORD wX, wY; UINT bIgnoreRegistry; MODEDESC mode; + DEVNODE devNode; + DISPLAYINFO DispInfo; + DWORD dwRc; /* Get the DPI, default to 96. */ wDpi = GetPrivateProfileInt( "display", "dpi", 96, "system.ini" ); @@ -92,13 +148,13 @@ void ReadDisplayConfig( void ) bIgnoreRegistry = GetPrivateProfileInt( "display", "IgnoreRegistry", 0, "system.ini" ); - if( !bIgnoreRegistry ) { - DISPLAYINFO DispInfo; - DWORD dwRc; + dwRc = CallVDDGetDispConf( VDD_GET_DISPLAY_CONFIG, sizeof( DispInfo ), &DispInfo ); + if( (dwRc != VDD_GET_DISPLAY_CONFIG) && !dwRc ) { + devNode = (DEVNODE)DispInfo.diDevNodeHandle; - dwRc = CallVDDGetDispConf( VDD_GET_DISPLAY_CONFIG, sizeof( DispInfo ), &DispInfo ); - if( (dwRc != VDD_GET_DISPLAY_CONFIG) && !dwRc ) { - /* Call succeeded, use the data. */ + /* Call succeeded, use the data. */ + if (!bIgnoreRegistry) + { wScrX = DispInfo.diXRes; wScrY = DispInfo.diYRes; wBpp = DispInfo.diBpp; @@ -108,9 +164,10 @@ void ReadDisplayConfig( void ) /* DPI might not be set, careful. */ if( DispInfo.diDPI ) wDpi = DispInfo.diDPI; - } else { - dbg_printf( "VDD_GET_DISPLAY_CONFIG failed, dwRc=%lX\n",dwRc ); } + } else { + dbg_printf( "VDD_GET_DISPLAY_CONFIG failed, dwRc=%lX\n",dwRc ); + devNode = 0; } mode.xRes = wScrX; @@ -129,9 +186,12 @@ void ReadDisplayConfig( void ) wPalettized = GetPrivateProfileInt( "display", "palettized", 1, "system.ini" ); else wPalettized = 0; + + return( devNode ); } -#define VDD_ID 10 /* Virtual Display Driver ID. */ +#define VDD_ID 10 /* Virtual Display Driver ID. */ +#define CONFIGMG_ID 51 /* Configuration Manager Driver ID. */ /* Get Device API Entry Point. */ void __far *int_2F_GetEP( unsigned ax, unsigned bx ); @@ -154,6 +214,8 @@ extern char __based( __segname( "_TEXT" ) ) *pText; #pragma aux DriverInit parm [cx] [di] [es si] UINT FAR DriverInit( UINT cbHeap, UINT hModule, LPSTR lpCmdLine ) { + DEVNODE devNode; + /* Lock the code segment. */ GlobalSmartPageLock( (__segment)pText ); @@ -166,7 +228,43 @@ UINT FAR DriverInit( UINT cbHeap, UINT hModule, LPSTR lpCmdLine ) dbg_printf( "DriverInit: VDDEntryPoint=%WP, OurVMHandle=%x\n", VDDEntryPoint, OurVMHandle ); /* Read the display configuration before doing anything else. */ - ReadDisplayConfig(); + LfbBase = 0; + devNode = ReadDisplayConfig(); + + /* Use the Configuration Manager to locate the base address of the linear framebuffer. */ + if( devNode ) { + RES_DES rd; + + ConfigMGEntryPoint = (DWORD)int_2F_GetEP( 0x1684, CONFIGMG_ID ); + + if( CM_Get_First_Log_Conf( &rd, devNode, ALLOC_LOG_CONF ) == CR_SUCCESS ) { + ULONG cbAllocMax = 0; + + /* Take the largest physical memory range in use by this device + * and store it into LfbBase. */ + while( CM_Get_Next_Res_Des( &rd, rd, ResType_Mem, NULL, 0 ) == CR_SUCCESS ) { + + /* Experimentally, no MEM_RES was found to be larger than 0x28 bytes + * with the QEMU VGA adapter, so this buffer is static, but it would + * be better to query the size (with CM_Get_Res_Des_Data_Size) and + * then use alloca here. */ + char memRes[0x28]; + + if( CM_Get_Res_Des_Data( rd, memRes, sizeof(memRes), 0 ) == CR_SUCCESS ) { + PMEM_DES pMemDes = (PMEM_DES)memRes; + ULONG cbAlloc = pMemDes->MD_Alloc_End - pMemDes->MD_Alloc_Base + 1; + + if( cbAlloc > cbAllocMax ) { + cbAllocMax = cbAlloc; + LfbBase = pMemDes->MD_Alloc_Base; + } + } + } + } + } + + dbg_printf("DriverInit: LfbBase is %lX\n", LfbBase); - return( 1 ); /* Success. */ + /* Return 1 (success) iff we located the physical address of the linear framebuffer. */ + return ( !!LfbBase ); } diff --git a/minidrv.h b/minidrv.h index 55a34b6..c7675cd 100644 --- a/minidrv.h +++ b/minidrv.h @@ -47,7 +47,7 @@ typedef struct { extern WORD FixModeInfo( LPMODEDESC lpMode ); extern int PhysicalEnable( void ); extern void FAR SetRAMDAC_far( UINT bStart, UINT bCount, RGBQUAD FAR *lpPal ); -extern void ReadDisplayConfig( void ); +extern DWORD ReadDisplayConfig( void ); extern void FAR RestoreDesktopMode( void ); extern FARPROC RepaintFunc; extern void HookInt2Fh( void ); @@ -76,6 +76,7 @@ extern RGBQUAD FAR *lpColorTable; /* Current color table. */ extern DWORD VDDEntryPoint; extern WORD OurVMHandle; +extern DWORD LfbBase; /* Inlines needed in multiple modules. */ diff --git a/modes.c b/modes.c index a4d0fa2..26d8996 100644 --- a/modes.c +++ b/modes.c @@ -305,7 +305,7 @@ int PhysicalEnable( void ) if( !iChipID ) { return( 0 ); } - dwPhysVRAM = BOXV_get_lfb_base( 0 ); + dwPhysVRAM = LfbBase; dbg_printf( "PhysicalEnable: Hardware detected, dwVideoMemorySize=%lX dwPhysVRAM=%lX\n", dwVideoMemorySize, dwPhysVRAM ); } @@ -371,7 +371,7 @@ UINT WINAPI __loadds ValidateMode( DISPVALMODE FAR *lpValMode ) rc = VALMODE_NO_WRONGDRV; break; } - dwPhysVRAM = BOXV_get_lfb_base( 0 ); + dwPhysVRAM = LfbBase; dbg_printf( "ValidateMode: Hardware detected, dwVideoMemorySize=%lX dwPhysVRAM=%lX\n", dwVideoMemorySize, dwPhysVRAM ); }