Skip to content

Commit

Permalink
Modifications for boxv9x to run on QEMU
Browse files Browse the repository at this point in the history
  • Loading branch information
phkelley committed Jan 21, 2023
1 parent 8d49b0c commit 3804560
Show file tree
Hide file tree
Showing 10 changed files with 196 additions and 83 deletions.
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.vscode/
res/*.obj
res/*.bin
*.obj
*.err
*.lib
*.drv
*.map
*.res
*.img
37 changes: 9 additions & 28 deletions boxv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
Expand Down Expand Up @@ -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.
Expand All @@ -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 );
}
1 change: 0 additions & 1 deletion boxv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
5 changes: 0 additions & 5 deletions boxv_io.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 ) );
}
54 changes: 26 additions & 28 deletions boxvint.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 -------------*/

Expand Down
3 changes: 1 addition & 2 deletions dbgprint.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 );

Expand Down
32 changes: 32 additions & 0 deletions ddk/configmg.h
Original file line number Diff line number Diff line change
@@ -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
130 changes: 114 additions & 16 deletions init.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ THE SOFTWARE.
#include <dibeng.h>
#include <minivdd.h>
#include "minidrv.h"

#include <configmg.h>

/* GlobalSmartPageLock is a semi-undocumented function. Not officially
* documented but described in KB Article Q180586. */
Expand All @@ -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)
Expand All @@ -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];

This comment has been minimized.

Copy link
@phkelley

phkelley Jan 21, 2023

Author Owner

This was a bug in the upstream driver where bx was being trashed.



#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" );
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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 );
Expand All @@ -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 );

Expand All @@ -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 );
}
Loading

0 comments on commit 3804560

Please sign in to comment.