[BOOTVID]: Fix completely broken VidInitialize routine. I have no idea what the origi...
[reactos.git] / reactos / drivers / base / bootvid / i386 / bootvid.c
1 #include "precomp.h"
2
3 /* PRIVATE FUNCTIONS *********************************************************/
4
5 BOOLEAN
6 NTAPI
7 VgaInterpretCmdStream(IN PUSHORT CmdStream)
8 {
9 PUCHAR Base = (PUCHAR)VgaRegisterBase;
10 USHORT Cmd;
11 UCHAR Major, Minor;
12 USHORT Count;
13 UCHAR Index;
14 PUSHORT Buffer;
15 PUSHORT ShortPort;
16 PUCHAR Port;
17 UCHAR Value;
18 USHORT ShortValue;
19
20 /* First make sure that we have a Command Stream */
21 if (!CmdStream) return TRUE;
22
23 /* Loop as long as we have commands */
24 while (*CmdStream)
25 {
26 /* Get the Major and Minor Function */
27 Cmd = *CmdStream;
28 Major = Cmd & 0xF0;
29 Minor = Cmd & 0x0F;
30
31 /* Move to the next command */
32 CmdStream++;
33
34 /* Check which major function this was */
35 if (Major == 0x10)
36 {
37 /* Now let's see the minor function */
38 if (Minor & CMD_STREAM_READ)
39 {
40 /* Now check the sub-type */
41 if (Minor & CMD_STREAM_USHORT)
42 {
43 /* The port is what is in the stream right now */
44 ShortPort = UlongToPtr((ULONG)*CmdStream);
45
46 /* Move to the next command */
47 CmdStream++;
48
49 /* Read USHORT from the port */
50 READ_PORT_USHORT(PtrToUlong(Base) + ShortPort);
51 }
52 else
53 {
54 /* The port is what is in the stream right now */
55 Port = UlongToPtr((ULONG)*CmdStream);
56
57 /* Move to the next command */
58 CmdStream++;
59
60 /* Read UCHAR from the port */
61 READ_PORT_UCHAR(PtrToUlong(Base) + Port);
62 }
63 }
64 else if (Minor & CMD_STREAM_WRITE_ARRAY)
65 {
66 /* Now check the sub-type */
67 if (Minor & CMD_STREAM_USHORT)
68 {
69 /* The port is what is in the stream right now */
70 ShortPort = UlongToPtr(Cmd);
71
72 /* Move to the next command and get the count */
73 Count = *(CmdStream++);
74
75 /* The buffer is what's next in the command stream */
76 Buffer = CmdStream++;
77
78 /* Write USHORT to the port */
79 WRITE_PORT_BUFFER_USHORT(PtrToUshort(Base) + ShortPort, Buffer, Count);
80
81 /* Move past the buffer in the command stream */
82 CmdStream += Count;
83 }
84 else
85 {
86 /* The port is what is in the stream right now */
87 Port = UlongToPtr(Cmd);
88
89 /* Move to the next command and get the count */
90 Count = *(CmdStream++);
91
92 /* Add the base to the port */
93 Port = PtrToUlong(Port) + Base;
94
95 /* Move to next command */
96 CmdStream++;
97
98 /* Loop the cmd array */
99 for (; Count; Count--, CmdStream++)
100 {
101 /* Get the byte we're writing */
102 Value = (UCHAR)*CmdStream;
103
104 /* Write UCHAR to the port */
105 WRITE_PORT_UCHAR(Port, Value);
106 }
107 }
108 }
109 else if (Minor & CMD_STREAM_USHORT)
110 {
111 /* Get the ushort we're writing and advance in the stream */
112 ShortValue = *CmdStream;
113 CmdStream++;
114
115 /* Write USHORT to the port (which is in cmd) */
116 WRITE_PORT_USHORT((PUSHORT)Base + Cmd, ShortValue);
117 }
118 else
119 {
120 /* The port is what is in the stream right now */
121 Port = UlongToPtr((ULONG)*CmdStream);
122
123 /* Get the uchar we're writing */
124 Value = (UCHAR)*++CmdStream;
125
126 /* Move to the next command */
127 CmdStream++;
128
129 /* Write UCHAR to the port (which is in cmd) */
130 WRITE_PORT_UCHAR(PtrToUlong(Base) + Port, Value);
131 }
132 }
133 else if (Major == 0x20)
134 {
135 /* Check the minor function. Note these are not flags anymore. */
136 switch (Minor)
137 {
138 case 0:
139 /* The port is what is in the stream right now */
140 ShortPort = UlongToPtr(*CmdStream);
141
142 /* Move to the next command and get the count */
143 Count = *(CmdStream++);
144
145 /* Move to the next command and get the value to write */
146 ShortValue = *(CmdStream++);
147
148 /* Add the base to the port */
149 ShortPort = PtrToUlong(ShortPort) + (PUSHORT)Base;
150
151 /* Move to next command */
152 CmdStream++;
153
154 /* Make sure we have data */
155 if (!ShortValue) continue;
156
157 /* Loop the cmd array */
158 for (; Count; Count--, CmdStream++, Value++)
159 {
160 /* Get the byte we're writing */
161 ShortValue += (*CmdStream) << 8;
162
163 /* Write USHORT to the port */
164 WRITE_PORT_USHORT(ShortPort, ShortValue);
165 }
166 break;
167 case 1:
168 /* The port is what is in the stream right now. Add the base too */
169 Port = *CmdStream + Base;
170
171 /* Move to the next command and get the count */
172 Count = *++CmdStream;
173
174 /* Move to the next command and get the index to write */
175 Index = (UCHAR)*++CmdStream;
176
177 /* Move to next command */
178 CmdStream++;
179
180 /* Loop the cmd array */
181 for (; Count; Count--, Index++)
182 {
183 /* Write the index */
184 WRITE_PORT_UCHAR(Port, Index);
185
186 /* Get the byte we're writing */
187 Value = (UCHAR)*CmdStream;
188
189 /* Move to next command */
190 CmdStream++;
191
192 /* Write UCHAR value to the port */
193 WRITE_PORT_UCHAR(Port, Value);
194 }
195 break;
196 case 2:
197 /* The port is what is in the stream right now. Add the base too */
198 Port = *CmdStream + Base;
199
200 /* Read the current value and add the stream data */
201 Value = READ_PORT_UCHAR(Port);
202 Value &= *CmdStream++;
203 Value ^= *CmdStream++;
204
205 /* Write the value */
206 WRITE_PORT_UCHAR(Port, Value);
207 break;
208 default:
209 /* Unknown command, fail */
210 return FALSE;
211 }
212 }
213 else if (Major != 0xF0)
214 {
215 /* Unknown major function, fail */
216 return FALSE;
217 }
218
219 /* Get the next command */
220 Cmd = *CmdStream;
221 }
222
223 /* If we got here, return success */
224 return TRUE;
225 }
226
227 BOOLEAN
228 NTAPI
229 VgaIsPresent(VOID)
230 {
231 UCHAR VgaReg, VgaReg2, VgaReg3;
232 UCHAR SeqReg, SeqReg2;
233 UCHAR i;
234
235 /* Read the VGA Address Register */
236 VgaReg = READ_PORT_UCHAR((PUCHAR)VgaRegisterBase + 0x3CE);
237
238 /* Select Read Map Select Register */
239 WRITE_PORT_UCHAR((PUCHAR)VgaRegisterBase + 0x3CE, 4);
240
241 /* Read it back...it should be 4 */
242 if (((READ_PORT_UCHAR((PUCHAR)VgaRegisterBase + 0x3CE)) & 0xF) != 4) return FALSE;
243
244 /* Read the VGA Data Register */
245 VgaReg2 = READ_PORT_UCHAR((PUCHAR)VgaRegisterBase + 0x3CF);
246
247 /* Enable all planes */
248 WRITE_PORT_UCHAR((PUCHAR)VgaRegisterBase + 0x3CF, 3);
249
250 /* Read it back...it should be 3 */
251 if (READ_PORT_UCHAR((PUCHAR)VgaRegisterBase + 0x3CF) != 0x3)
252 {
253 /* Reset the registers and fail */
254 WRITE_PORT_UCHAR((PUCHAR)VgaRegisterBase + 0x3CF, 0);
255 return FALSE;
256 }
257
258 /* Select Bit Mask Register */
259 WRITE_PORT_UCHAR((PUCHAR)VgaRegisterBase + 0x3CE, 8);
260
261 /* Read it back...it should be 8 */
262 if (((READ_PORT_UCHAR((PUCHAR)VgaRegisterBase + 0x3CE)) & 0xF) != 8)
263 {
264 /* Reset the registers and fail */
265 WRITE_PORT_UCHAR((PUCHAR)VgaRegisterBase + 0x3CE, 4);
266 WRITE_PORT_UCHAR((PUCHAR)VgaRegisterBase + 0x3CF, 0);
267 return FALSE;
268 }
269
270 /* Read the VGA Data Register */
271 VgaReg3 = READ_PORT_UCHAR((PUCHAR)VgaRegisterBase + 0x3CF);
272
273 /* Loop bitmasks */
274 for (i = 0xBB; i; i >>= 1)
275 {
276 /* Set bitmask */
277 WRITE_PORT_UCHAR((PUCHAR)VgaRegisterBase + 0x3CF, i);
278
279 /* Read it back...it should be the same */
280 if (READ_PORT_UCHAR((PUCHAR)VgaRegisterBase + 0x3CF) != i)
281 {
282 /* Reset the registers and fail */
283 WRITE_PORT_UCHAR((PUCHAR)VgaRegisterBase + 0x3CF, 0xFF);
284 WRITE_PORT_UCHAR((PUCHAR)VgaRegisterBase + 0x3CE, 4);
285 WRITE_PORT_UCHAR((PUCHAR)VgaRegisterBase + 0x3CF, 0);
286 return FALSE;
287 }
288 }
289
290 /* Select Read Map Select Register */
291 WRITE_PORT_UCHAR((PUCHAR)VgaRegisterBase + 0x3CE, 4);
292
293 /* Read it back...it should be 3 */
294 if (READ_PORT_UCHAR((PUCHAR)VgaRegisterBase + 0x3CF) != 3)
295 {
296 /* Reset the registers and fail */
297 WRITE_PORT_UCHAR((PUCHAR)VgaRegisterBase + 0x3CF, 0);
298 WRITE_PORT_UCHAR((PUCHAR)VgaRegisterBase + 0x3CE, 8);
299 WRITE_PORT_UCHAR((PUCHAR)VgaRegisterBase + 0x3CF, 0xFF);
300 return FALSE;
301 }
302
303 /* Write the registers we read earlier */
304 WRITE_PORT_UCHAR((PUCHAR)VgaRegisterBase + 0x3CF, VgaReg2);
305 WRITE_PORT_UCHAR((PUCHAR)VgaRegisterBase + 0x3CE, 8);
306 WRITE_PORT_UCHAR((PUCHAR)VgaRegisterBase + 0x3CF, VgaReg3);
307 WRITE_PORT_UCHAR((PUCHAR)VgaRegisterBase + 0x3CE, VgaReg);
308
309 /* Read sequencer address */
310 SeqReg = READ_PORT_UCHAR((PUCHAR)VgaRegisterBase + 0x3C4);
311
312 /* Select memory mode register */
313 WRITE_PORT_UCHAR((PUCHAR)VgaRegisterBase + 0x3C4, 4);
314
315 /* Read it back...it should still be 4 */
316 if (((READ_PORT_UCHAR((PUCHAR)VgaRegisterBase + 0x3C4)) & 7) != 4)
317 {
318 /* Fail */
319 return FALSE;
320 }
321
322 /* Read sequencer Data */
323 SeqReg2 = READ_PORT_UCHAR((PUCHAR)VgaRegisterBase + 0x3C5);
324
325 /* Write null plane */
326 WRITE_PORT_USHORT((PUSHORT)VgaRegisterBase + 0x3C4, 0x100);
327
328 /* Write sequencer flag */
329 WRITE_PORT_UCHAR((PUCHAR)VgaRegisterBase + 0x3C5, SeqReg2 ^ 8);
330
331 /* Read it back */
332 if ((READ_PORT_UCHAR((PUCHAR)VgaRegisterBase + 0x3C5)) != (SeqReg2 ^ 8))
333 {
334 /* Not the same value...restore registers and fail */
335 WRITE_PORT_UCHAR((PUCHAR)VgaRegisterBase + 0x3C5, 2);
336 WRITE_PORT_USHORT((PUSHORT)VgaRegisterBase + 0x3C4, 0x300);
337 return FALSE;
338 }
339
340 /* Now write the registers we read */
341 WRITE_PORT_UCHAR((PUCHAR)VgaRegisterBase + 0x3C5, SeqReg2);
342 WRITE_PORT_USHORT((PUSHORT)VgaRegisterBase + 0x3C4, 0x300);
343 WRITE_PORT_UCHAR((PUCHAR)VgaRegisterBase + 0x3C4, SeqReg);
344
345 /* VGA is present! */
346 return TRUE;
347 }
348
349 /* PUBLIC FUNCTIONS **********************************************************/
350
351 /*
352 * @implemented
353 */
354 BOOLEAN
355 NTAPI
356 VidInitialize(IN BOOLEAN SetMode)
357 {
358 ULONG Context = 0;
359 PHYSICAL_ADDRESS TranslatedAddress;
360 PHYSICAL_ADDRESS NullAddress = {{0, 0}}, VgaAddress;
361 ULONG AddressSpace = 1;
362 BOOLEAN Result;
363 ULONG_PTR Base;
364
365 /* Make sure that we have a bus translation function */
366 if (!HalFindBusAddressTranslation) return FALSE;
367
368 /* Get the VGA Register address */
369 Result = HalFindBusAddressTranslation(NullAddress,
370 &AddressSpace,
371 &TranslatedAddress,
372 &Context,
373 TRUE);
374 if (!Result) return FALSE;
375
376 /* Loop trying to find posssible VGA base addresses */
377 while (TRUE)
378 {
379 /* See if this is I/O Space, which we need to map */
380 if (!AddressSpace)
381 {
382 /* Map it */
383 Base = (ULONG_PTR)MmMapIoSpace(TranslatedAddress, 0x400, MmNonCached);
384 }
385 else
386 {
387 /* The base is the translated address, no need to map I/O space */
388 Base = TranslatedAddress.LowPart;
389 }
390
391 /* Try to see if this is VGA */
392 VgaRegisterBase = Base;
393 if (VgaIsPresent())
394 {
395 /* Translate the VGA Memory Address */
396 VgaAddress.LowPart = 0xA0000;
397 AddressSpace = 0;
398 Result = HalFindBusAddressTranslation(VgaAddress,
399 &AddressSpace,
400 &TranslatedAddress,
401 &Context,
402 FALSE);
403 if (Result) break;
404
405 /* Try to see if there's any other address */
406 Result = HalFindBusAddressTranslation(NullAddress,
407 &AddressSpace,
408 &TranslatedAddress,
409 &Context,
410 TRUE);
411 if (!Result) return FALSE;
412 }
413 else
414 {
415 /* It's not, so unmap the I/O space if we mapped it */
416 if (!AddressSpace) MmUnmapIoSpace((PVOID)VgaRegisterBase, 0x400);
417 }
418 }
419
420 /* Success! See if this is I/O Space, which we need to map */
421 if (!AddressSpace)
422 {
423 /* Map it */
424 Base = (ULONG_PTR)MmMapIoSpace(TranslatedAddress,
425 0x20000,
426 MmNonCached);
427 }
428 else
429 {
430 /* The base is the translated address, no need to map I/O space */
431 Base = TranslatedAddress.LowPart;
432 }
433
434 /* Set the VGA Memory Base */
435 VgaBase = Base;
436
437 /* Now check if we have to set the mode */
438 if (SetMode)
439 {
440 /* Reset the display */
441 HalResetDisplay();
442 curr_x = 0;
443 curr_y = 0;
444
445 /* Initialize it */
446 VgaInterpretCmdStream(AT_Initialization);
447 }
448
449 /* VGA is ready */
450 return TRUE;
451 }
452
453 /*
454 * @implemented
455 */
456 VOID
457 NTAPI
458 VidResetDisplay(IN BOOLEAN HalReset)
459 {
460 /* Clear the current position */
461 curr_x = 0;
462 curr_y = 0;
463
464 /* Clear the screen with HAL if we were asked to */
465 if (HalReset) HalResetDisplay();
466
467 /* Re-initialize the VGA Display */
468 VgaInterpretCmdStream(AT_Initialization);
469
470 /* Re-initialize the palette and fill the screen black */
471 InitializePalette();
472 VidSolidColorFill(0, 0, 639, 479, 0);
473 }
474