ReactOS 0.4.17-dev-1344-g1103f43
bootvid.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Boot Video Driver for VGA-compatible cards
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Main file
5 * COPYRIGHT: Copyright 2007 Alex Ionescu <alex.ionescu@reactos.org>
6 * Copyright 2019 Hermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
7 */
8
9#include "precomp.h"
10
11/* PRIVATE FUNCTIONS *********************************************************/
12
13static BOOLEAN
15 _In_ const USHORT* CmdStream)
16{
17 USHORT Cmd;
18 UCHAR Major, Minor;
23 USHORT ShortValue;
24
25 /* Loop as long as we have commands */
26 while (*CmdStream != EOD)
27 {
28 /* Get the next command and its Major and Minor functions */
29 Cmd = *CmdStream++;
30 Major = Cmd & 0xF0;
31 Minor = Cmd & 0x0F;
32
33 /* Check which major function this is */
34 if (Major == INOUT)
35 {
36 /* Check the minor function */
37 if (Minor & IO /* CMD_STREAM_READ */)
38 {
39 /* Check the sub-type */
40 if (Minor & BW /* CMD_STREAM_USHORT */)
41 {
42 /* Get the port and read an USHORT from it */
43 Port = *CmdStream++;
44 ShortValue = __inpw(Port);
45 }
46 else // if (Minor & CMD_STREAM_WRITE)
47 {
48 /* Get the port and read an UCHAR from it */
49 Port = *CmdStream++;
50 Value = __inpb(Port);
51 }
52 }
53 else if (Minor & MULTI /* CMD_STREAM_WRITE_ARRAY */)
54 {
55 /* Check the sub-type */
56 if (Minor & BW /* CMD_STREAM_USHORT */)
57 {
58 /* Get the port and the count of elements */
59 Port = *CmdStream++;
60 Count = *CmdStream++;
61
62 /* Write the USHORT to the port; the buffer is what's in the command stream */
64
65 /* Move past the buffer in the command stream */
66 CmdStream += Count;
67 }
68 else // if (Minor & CMD_STREAM_WRITE)
69 {
70 /* Get the port and the count of elements */
71 Port = *CmdStream++;
72 Count = *CmdStream++;
73
74 /* Loop the command array */
75 for (; Count; --Count, ++CmdStream)
76 {
77 /* Get the UCHAR and write it to the port */
78 Value = (UCHAR)*CmdStream;
80 }
81 }
82 }
83 else if (Minor & BW /* CMD_STREAM_USHORT */)
84 {
85 /* Get the port */
86 Port = *CmdStream++;
87
88 /* Get the USHORT and write it to the port */
89 ShortValue = *CmdStream++;
90 __outpw(Port, ShortValue);
91 }
92 else // if (Minor & CMD_STREAM_WRITE)
93 {
94 /* Get the port */
95 Port = *CmdStream++;
96
97 /* Get the UCHAR and write it to the port */
98 Value = (UCHAR)*CmdStream++;
100 }
101 }
102 else if (Major == METAOUT)
103 {
104 /* Check the minor function. Note these are not flags. */
105 switch (Minor)
106 {
107 case INDXOUT:
108 {
109 /* Get the port, the count of elements and the start index */
110 Port = *CmdStream++;
111 Count = *CmdStream++;
112 Index = (UCHAR)*CmdStream++;
113
114 /* Loop the command array */
115 for (; Count; --Count, ++Index, ++CmdStream)
116 {
117 /* Get the USHORT and write it to the port */
118 ShortValue = (USHORT)Index + ((*CmdStream) << 8);
119 __outpw(Port, ShortValue);
120 }
121 break;
122 }
123
124 case ATCOUT:
125 {
126 /* Get the port, the count of elements and the start index */
127 Port = *CmdStream++;
128 Count = *CmdStream++;
129 Index = (UCHAR)*CmdStream++;
130
131 /* Loop the command array */
132 for (; Count; --Count, ++Index, ++CmdStream)
133 {
134 /* Write the index */
136
137 /* Get the UCHAR and write it to the port */
138 Value = (UCHAR)*CmdStream;
140 }
141 break;
142 }
143
144 case MASKOUT:
145 {
146 /* Get the port */
147 Port = *CmdStream++;
148
149 /* Read the current value and add the stream data */
150 Value = __inpb(Port);
151 Value &= *CmdStream++;
152 Value ^= *CmdStream++;
153
154 /* Write the value */
156 break;
157 }
158
159 default:
160 /* Unknown command, fail */
161 return FALSE;
162 }
163 }
164 else if (Major != NCMD)
165 {
166 /* Unknown major function, fail */
167 return FALSE;
168 }
169 }
170
171 /* If we got here, return success */
172 return TRUE;
173}
174
175static BOOLEAN
177{
178 UCHAR OrgGCAddr, OrgReadMap, OrgBitMask;
179 UCHAR OrgSCAddr, OrgMemMode;
180 UCHAR i;
181
182#if (NTDDI_VERSION >= NTDDI_WIN7)
183 /* Check whether the current platform supports IO port access
184 * and fail if not, since we won't be able to use VGA IO ports */
185 if ((HALPRIVATEDISPATCH->Version >= 13) &&
187 {
188 return FALSE;
189 }
190#endif
191
192 /* Remember the original state of the Graphics Controller Address register */
194
195 /*
196 * Write the Read Map register with a known state so we can verify
197 * that it isn't changed after we fool with the Bit Mask. This ensures
198 * that we're dealing with indexed registers, since both the Read Map and
199 * the Bit Mask are addressed at GRAPH_DATA_PORT.
200 */
202
203 /*
204 * If we can't read back the Graphics Address register setting we just
205 * performed, it's not readable and this isn't a VGA.
206 */
208 return FALSE;
209
210 /*
211 * Set the Read Map register to a known state.
212 */
215
216 /* Read it back... it should be the same */
218 {
219 /*
220 * The Read Map setting we just performed can't be read back; not a
221 * VGA. Restore the default Read Map state and fail.
222 */
224 return FALSE;
225 }
226
227 /* Remember the original setting of the Bit Mask register */
229
230 /* Read it back... it should be the same */
232 {
233 /*
234 * The Graphics Address register setting we just made can't be read
235 * back; not a VGA. Restore the default Read Map state and fail.
236 */
239 return FALSE;
240 }
241
242 /* Read the VGA Data Register */
244
245 /*
246 * Set up the initial test mask we'll write to and read from the Bit Mask,
247 * and loop on the bitmasks.
248 */
249 for (i = 0xBB; i; i >>= 1)
250 {
251 /* Write the test mask to the Bit Mask */
253
254 /* Read it back... it should be the same */
256 {
257 /*
258 * The Bit Mask is not properly writable and readable; not a VGA.
259 * Restore the Bit Mask and Read Map to their default states and fail.
260 */
264 return FALSE;
265 }
266 }
267
268 /*
269 * There's something readable at GRAPH_DATA_PORT; now switch back and
270 * make sure that the Read Map register hasn't changed, to verify that
271 * we're dealing with indexed registers.
272 */
274
275 /* Read it back */
277 {
278 /*
279 * The Read Map is not properly writable and readable; not a VGA.
280 * Restore the Bit Mask and Read Map to their default states, in case
281 * this is an EGA, so subsequent writes to the screen aren't garbled.
282 * Then fail.
283 */
287 return FALSE;
288 }
289
290 /*
291 * We've pretty surely verified the existence of the Bit Mask register.
292 * Put the Graphics Controller back to the original state.
293 */
298
299 /*
300 * Now, check for the existence of the Chain4 bit.
301 */
302
303 /*
304 * Remember the original states of the Sequencer Address and Memory Mode
305 * registers.
306 */
309
310 /* Read it back... it should be the same */
312 {
313 /*
314 * Couldn't read back the Sequencer Address register setting
315 * we just performed, fail.
316 */
317 return FALSE;
318 }
319
320 /* Read sequencer Data */
321 OrgMemMode = __inpb(VGA_BASE_IO_PORT + SEQ_DATA_PORT);
322
323 /*
324 * Toggle the Chain4 bit and read back the result. This must be done during
325 * sync reset, since we're changing the chaining state.
326 */
327
328 /* Begin sync reset */
330
331 /* Toggle the Chain4 bit */
334
335 /* Read it back... it should be the same */
336 if (__inpb(VGA_BASE_IO_PORT + SEQ_DATA_PORT) != (OrgMemMode ^ CHAIN4_MASK))
337 {
338 /*
339 * Chain4 bit is not there, not a VGA.
340 * Set text mode default for Memory Mode register.
341 */
343
344 /* End sync reset */
346
347 /* Fail */
348 return FALSE;
349 }
350
351 /*
352 * It's a VGA.
353 */
354
355 /* Restore the original Memory Mode setting */
357
358 /* End sync reset */
360
361 /* Restore the original Sequencer Address setting */
363
364 /* VGA is present! */
365 return TRUE;
366}
367
368/* PUBLIC FUNCTIONS **********************************************************/
369
371NTAPI
373 _In_ BOOLEAN SetMode)
374{
375 ULONG_PTR Context = 0;
377 PHYSICAL_ADDRESS NullAddress = {{0, 0}}, VgaAddress;
381
382 /* Make sure that we have a bus translation function */
384
385 /* Loop trying to find possible VGA base addresses */
386 while (TRUE)
387 {
388 /* Get the VGA Register address */
389 AddressSpace = 1;
393 &Context,
394 TRUE);
395 if (!Result) return FALSE;
396
397 /* See if this is I/O Space, which we need to map */
398 if (!AddressSpace)
399 {
400 /* Map it */
402 }
403 else
404 {
405 /* The base is the translated address, no need to map I/O space */
407 }
408
409 /* Try to see if this is VGA */
411 if (VgaIsPresent())
412 {
413 /* Translate the VGA Memory Address */
414 VgaAddress.LowPart = MEM_VGA;
415 VgaAddress.HighPart = 0;
416 AddressSpace = 0;
420 &Context,
421 FALSE);
422 if (Result) break;
423 }
424 else
425 {
426 /* It's not, so unmap the I/O space if we mapped it */
428 }
429
430 /* Continue trying to see if there's any other address */
431 }
432
433 /* Success! See if this is I/O Space, which we need to map */
434 if (!AddressSpace)
435 {
436 /* Map it */
440 }
441 else
442 {
443 /* The base is the translated address, no need to map I/O space */
445 }
446
447 /* Set the VGA Memory Base */
448 VgaBase = Base;
449
451
452 /* Check whether we have to set the video mode */
453 if (SetMode)
454 {
455 /* Clear the current position */
456 VidpCurrentX = 0;
457 VidpCurrentY = 0;
458
459 /* Reset the display and initialize it */
460 if (HalResetDisplay())
461 {
462 /* The HAL handled the display, re-initialize only the AC registers */
464 }
465 else
466 {
467 /* The HAL didn't handle the display, fully re-initialize the VGA */
469 }
470 }
471
472 return TRUE;
473}
474
475VOID
477 _In_ BOOLEAN SetMode)
478{
480
481 /* Reset the video mode with HAL if requested */
482 if (SetMode && !HalResetDisplay())
483 {
484 /* The HAL didn't handle the display, fully re-initialize the VGA */
486 }
487
488 /* Always re-initialize the AC registers */
490
491 /* Re-initialize the palette and fill the screen black */
494}
unsigned char BOOLEAN
Definition: actypes.h:127
VOID NTAPI VidSolidColorFill(_In_ ULONG Left, _In_ ULONG Top, _In_ ULONG Right, _In_ ULONG Bottom, _In_ UCHAR Color)
Definition: bootvid.c:298
VOID ResetDisplay(_In_ BOOLEAN SetMode)
Definition: bootvid.c:263
BOOLEAN NTAPI VidInitialize(_In_ BOOLEAN SetMode)
Definition: bootvid.c:231
#define WRITE_PORT_BUFFER_USHORT(port, buffer, count)
Definition: hardware.h:34
ULONG Minor
Definition: classlib.cpp:73
Walk Base
Definition: desccheck.cpp:2270
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
ULONG VidpCurrentY
Definition: console.c:16
ULONG VidpCurrentX
Definition: console.c:15
const USHORT VGA_640x480[]
Definition: bootdata.c:47
const USHORT AT_Initialization[]
Definition: bootdata.c:16
#define ATCOUT
Definition: cmdcnst.h:76
#define NCMD
Definition: cmdcnst.h:63
#define INOUT
Definition: cmdcnst.h:61
#define INDXOUT
Definition: cmdcnst.h:75
#define BW
Definition: cmdcnst.h:70
#define MASKOUT
Definition: cmdcnst.h:77
#define EOD
Definition: cmdcnst.h:60
#define METAOUT
Definition: cmdcnst.h:62
#define MULTI
Definition: cmdcnst.h:69
#define IO
Definition: cmdcnst.h:71
#define START_SYNC_RESET_VALUE
Definition: vga.h:123
#define SEQ_ADDRESS_PORT
Definition: vga.h:69
#define SEQ_ADDR_MASK
Definition: vga.h:145
#define GRAPH_ADDRESS_PORT
Definition: vga.h:81
#define GRAPH_DATA_PORT
Definition: vga.h:82
#define MEM_VGA_SIZE
Definition: vga.h:22
#define BIT_MASK_DEFAULT
Definition: vga.h:167
#define GRAPH_ADDR_MASK
Definition: vga.h:144
#define CHAIN4_MASK
Definition: vga.h:151
#define IND_BIT_MASK
Definition: vga.h:114
#define READ_MAP_DEFAULT
Definition: vga.h:168
#define IND_READ_MAP
Definition: vga.h:111
#define IND_SYNC_RESET
Definition: vga.h:115
#define READ_MAP_TEST_SETTING
Definition: vga.h:159
#define IND_MEMORY_MODE
Definition: vga.h:117
#define VGA_BASE_IO_PORT
Definition: vga.h:38
#define SEQ_DATA_PORT
Definition: vga.h:70
#define END_SYNC_RESET_VALUE
Definition: vga.h:125
#define MEM_VGA
Definition: vga.h:21
#define MEMORY_MODE_TEXT_DEFAULT
Definition: vga.h:166
#define ULONG_PTR
Definition: config.h:101
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
CPPORT Port[4]
Definition: headless.c:38
static BOOLEAN VgaIsPresent(VOID)
Definition: bootvid.c:176
static BOOLEAN VgaInterpretCmdStream(_In_ const USHORT *CmdStream)
Definition: bootvid.c:14
VOID NTAPI MmUnmapIoSpace(IN PVOID BaseAddress, IN SIZE_T NumberOfBytes)
Definition: iosup.c:192
PVOID NTAPI MmMapIoSpace(IN PHYSICAL_ADDRESS PhysicalAddress, IN SIZE_T NumberOfBytes, IN MEMORY_CACHING_TYPE CacheType)
Definition: iosup.c:47
_In_ PIRP _In_ PIO_COMPLETION_ROUTINE _In_ PVOID Context
Definition: kse.h:81
#define HalFindBusAddressTranslation
Definition: halfuncs.h:44
#define HalQueryIoPortAccessSupported
Definition: halfuncs.h:92
#define HalResetDisplay
Definition: halfuncs.h:45
#define HALPRIVATEDISPATCH
Definition: haltypes.h:2101
#define _In_
Definition: no_sal2.h:158
#define InitializePalette
Definition: pc98.h:26
#define SCREEN_WIDTH
Definition: pc98video.c:24
#define SCREEN_HEIGHT
Definition: pc98video.c:25
ULONG_PTR VgaRegisterBase
Definition: vga.c:69
#define __inpb(Port)
Definition: pc.h:27
#define __outpw(Port, Value)
Definition: pc.h:36
ULONG_PTR VgaBase
Definition: vga.c:70
@ VGA_GC_STATE_UNINITIALIZED
Definition: pc.h:14
VGA_GRAPHICS_CONTROLLER_STATE VgaGCState
Definition: vga.c:68
#define __outpb(Port, Value)
Definition: pc.h:33
#define __inpw(Port)
Definition: pc.h:30
unsigned short USHORT
Definition: pedump.c:61
@ Cmd
Definition: sacdrv.h:278
#define BV_COLOR_BLACK
Definition: display.h:15
unsigned char UCHAR
Definition: typedefs.h:53
#define NTAPI
Definition: typedefs.h:36
uint16_t * PUSHORT
Definition: typedefs.h:56
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint32_t ULONG
Definition: typedefs.h:59
ULONG LowPart
Definition: typedefs.h:106
USHORT Count
Definition: userreq.cpp:200
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409
_In_ ULONG _In_ PHYSICAL_ADDRESS _Inout_ PULONG _Out_ PPHYSICAL_ADDRESS TranslatedAddress
Definition: iofuncs.h:2593
_In_ ULONG _In_ PHYSICAL_ADDRESS _Inout_ PULONG AddressSpace
Definition: iofuncs.h:2592
@ MmNonCached
Definition: mmtypes.h:129