@@ -29,7 +29,7 @@ THE SOFTWARE.
29
29
#include <dibeng.h>
30
30
#include <minivdd.h>
31
31
#include "minidrv.h"
32
-
32
+ #include <configmg.h>
33
33
34
34
/* GlobalSmartPageLock is a semi-undocumented function. Not officially
35
35
* documented but described in KB Article Q180586. */
@@ -41,8 +41,10 @@ WORD wDpi = 96; /* Current DPI setting. */
41
41
WORD wBpp = 8 ; /* Current BPP setting. */
42
42
WORD wPalettized = 0 ; /* Non-zero if palettized. */
43
43
44
- WORD OurVMHandle = 0 ; /* The current VM's ID. */
45
- DWORD VDDEntryPoint = 0 ; /* The VDD entry point. */
44
+ WORD OurVMHandle = 0 ; /* The current VM's ID. */
45
+ DWORD VDDEntryPoint = 0 ; /* The VDD entry point. */
46
+ DWORD ConfigMGEntryPoint = 0 ; /* The configuration manager entry point. */
47
+ DWORD LfbBase = 0 ; /* The physical base address of the linear framebuffer. */
46
48
47
49
/* On Entry:
48
50
* EAX = Function code (VDD_GET_DISPLAY_CONFIG)
@@ -65,18 +67,72 @@ extern DWORD CallVDDGetDispConf( WORD Function, WORD wDInfSize, LPVOID pDInf );
65
67
"call dword ptr VDDEntryPoint"\
66
68
"mov edx, eax" \
67
69
"shr edx, 16" \
68
- parm [ax] [cx] [es di];
70
+ parm [ax] [cx] [es di] modify [bx] ;
69
71
70
72
71
73
#pragma code_seg( _INIT )
72
74
75
+ /* Get the first logical configuration for a devnode.
76
+ */
77
+ CONFIGRET static _near _cdecl CM_Get_First_Log_Conf (
78
+ PLOG_CONF plcLogConf ,
79
+ DEVNODE dnDevNode ,
80
+ ULONG ulFlags )
81
+ {
82
+ WORD wRc = 0 ;
83
+
84
+ _asm { mov eax , 01 Ah }; /* CM_GET_FIRST_LOG_CONF */
85
+ _asm { call ConfigMGEntryPoint };
86
+ _asm { mov wRc , ax };
87
+
88
+ return ( wRc );
89
+ }
90
+
91
+ /* Get the next resource descriptor of a given type.
92
+ */
93
+ CONFIGRET static _near _cdecl CM_Get_Next_Res_Des (
94
+ PRES_DES prdResDes ,
95
+ RES_DES CurrentResDesOrLogConf ,
96
+ RESOURCEID ForResource ,
97
+ PRESOURCEID pResourceID ,
98
+ ULONG ulFlags )
99
+ {
100
+ WORD wRc = 0 ;
101
+
102
+ _asm { mov eax , 01F h }; /* CM_GET_NEXT_RES_DES */
103
+ _asm { call ConfigMGEntryPoint };
104
+ _asm { mov wRc , ax };
105
+
106
+ return ( wRc );
107
+ }
108
+
109
+ /* Get the data for a resource descriptor.
110
+ */
111
+ CONFIGRET static _near _cdecl CM_Get_Res_Des_Data (
112
+ RES_DES rdResDes ,
113
+ PFARVOID Buffer ,
114
+ ULONG BufferLen ,
115
+ ULONG ulFlags )
116
+ {
117
+ WORD wRc = 0 ;
118
+
119
+ _asm { mov eax , 022 h }; /* CM_GET_RES_DES_DATA */
120
+ _asm { call ConfigMGEntryPoint };
121
+ _asm { mov wRc , ax };
122
+
123
+ return ( wRc );
124
+ }
125
+
73
126
/* Read the display settings from SYSTEM.INI or Registry.
74
127
*/
75
- void ReadDisplayConfig ( void )
128
+ DEVNODE ReadDisplayConfig ( void )
76
129
{
77
130
WORD wX , wY ;
78
131
UINT bIgnoreRegistry ;
79
132
MODEDESC mode ;
133
+ DEVNODE devNode ;
134
+ DISPLAYINFO DispInfo ;
135
+ DWORD dwRc ;
80
136
81
137
/* Get the DPI, default to 96. */
82
138
wDpi = GetPrivateProfileInt ( "display" , "dpi" , 96 , "system.ini" );
@@ -92,13 +148,13 @@ void ReadDisplayConfig( void )
92
148
93
149
bIgnoreRegistry = GetPrivateProfileInt ( "display" , "IgnoreRegistry" , 0 , "system.ini" );
94
150
95
- if ( ! bIgnoreRegistry ) {
96
- DISPLAYINFO DispInfo ;
97
- DWORD dwRc ;
151
+ dwRc = CallVDDGetDispConf ( VDD_GET_DISPLAY_CONFIG , sizeof ( DispInfo ), & DispInfo );
152
+ if ( ( dwRc != VDD_GET_DISPLAY_CONFIG ) && ! dwRc ) {
153
+ devNode = ( DEVNODE ) DispInfo . diDevNodeHandle ;
98
154
99
- dwRc = CallVDDGetDispConf ( VDD_GET_DISPLAY_CONFIG , sizeof ( DispInfo ), & DispInfo );
100
- if ( ( dwRc != VDD_GET_DISPLAY_CONFIG ) && ! dwRc ) {
101
- /* Call succeeded, use the data. */
155
+ /* Call succeeded, use the data. */
156
+ if (! bIgnoreRegistry )
157
+ {
102
158
wScrX = DispInfo .diXRes ;
103
159
wScrY = DispInfo .diYRes ;
104
160
wBpp = DispInfo .diBpp ;
@@ -108,9 +164,10 @@ void ReadDisplayConfig( void )
108
164
/* DPI might not be set, careful. */
109
165
if ( DispInfo .diDPI )
110
166
wDpi = DispInfo .diDPI ;
111
- } else {
112
- dbg_printf ( "VDD_GET_DISPLAY_CONFIG failed, dwRc=%lX\n" ,dwRc );
113
167
}
168
+ } else {
169
+ dbg_printf ( "VDD_GET_DISPLAY_CONFIG failed, dwRc=%lX\n" ,dwRc );
170
+ devNode = 0 ;
114
171
}
115
172
116
173
mode .xRes = wScrX ;
@@ -129,9 +186,12 @@ void ReadDisplayConfig( void )
129
186
wPalettized = GetPrivateProfileInt ( "display" , "palettized" , 1 , "system.ini" );
130
187
else
131
188
wPalettized = 0 ;
189
+
190
+ return ( devNode );
132
191
}
133
192
134
- #define VDD_ID 10 /* Virtual Display Driver ID. */
193
+ #define VDD_ID 10 /* Virtual Display Driver ID. */
194
+ #define CONFIGMG_ID 51 /* Configuration Manager Driver ID. */
135
195
136
196
/* Get Device API Entry Point. */
137
197
void __far * int_2F_GetEP ( unsigned ax , unsigned bx );
@@ -154,6 +214,8 @@ extern char __based( __segname( "_TEXT" ) ) *pText;
154
214
#pragma aux DriverInit parm [cx] [di] [es si]
155
215
UINT FAR DriverInit ( UINT cbHeap , UINT hModule , LPSTR lpCmdLine )
156
216
{
217
+ DEVNODE devNode ;
218
+
157
219
/* Lock the code segment. */
158
220
GlobalSmartPageLock ( (__segment )pText );
159
221
@@ -166,7 +228,43 @@ UINT FAR DriverInit( UINT cbHeap, UINT hModule, LPSTR lpCmdLine )
166
228
dbg_printf ( "DriverInit: VDDEntryPoint=%WP, OurVMHandle=%x\n" , VDDEntryPoint , OurVMHandle );
167
229
168
230
/* Read the display configuration before doing anything else. */
169
- ReadDisplayConfig ();
231
+ LfbBase = 0 ;
232
+ devNode = ReadDisplayConfig ();
233
+
234
+ /* Use the Configuration Manager to locate the base address of the linear framebuffer. */
235
+ if ( devNode ) {
236
+ RES_DES rd ;
237
+
238
+ ConfigMGEntryPoint = (DWORD )int_2F_GetEP ( 0x1684 , CONFIGMG_ID );
239
+
240
+ if ( CM_Get_First_Log_Conf ( & rd , devNode , ALLOC_LOG_CONF ) == CR_SUCCESS ) {
241
+ ULONG cbAllocMax = 0 ;
242
+
243
+ /* Take the largest physical memory range in use by this device
244
+ * and store it into LfbBase. */
245
+ while ( CM_Get_Next_Res_Des ( & rd , rd , ResType_Mem , NULL , 0 ) == CR_SUCCESS ) {
246
+
247
+ /* Experimentally, no MEM_RES was found to be larger than 0x28 bytes
248
+ * with the QEMU VGA adapter, so this buffer is static, but it would
249
+ * be better to query the size (with CM_Get_Res_Des_Data_Size) and
250
+ * then use alloca here. */
251
+ char memRes [0x28 ];
252
+
253
+ if ( CM_Get_Res_Des_Data ( rd , memRes , sizeof (memRes ), 0 ) == CR_SUCCESS ) {
254
+ PMEM_DES pMemDes = (PMEM_DES )memRes ;
255
+ ULONG cbAlloc = pMemDes -> MD_Alloc_End - pMemDes -> MD_Alloc_Base + 1 ;
256
+
257
+ if ( cbAlloc > cbAllocMax ) {
258
+ cbAllocMax = cbAlloc ;
259
+ LfbBase = pMemDes -> MD_Alloc_Base ;
260
+ }
261
+ }
262
+ }
263
+ }
264
+ }
265
+
266
+ dbg_printf ("DriverInit: LfbBase is %lX\n" , LfbBase );
170
267
171
- return ( 1 ); /* Success. */
268
+ /* Return 1 (success) iff we located the physical address of the linear framebuffer. */
269
+ return ( !!LfbBase );
172
270
}
0 commit comments