[BOOTVID] Don't increment an uninitialized and unused variable, bug #5103
[reactos.git] / reactos / drivers / base / bootvid / arm / bootvid.c
1 #include "precomp.h"
2 #define NDEBUG
3 #include "debug.h"
4
5 #define LCDTIMING0_PPL(x) ((((x) / 16 - 1) & 0x3f) << 2)
6 #define LCDTIMING1_LPP(x) (((x) & 0x3ff) - 1)
7 #define LCDCONTROL_LCDPWR (1 << 11)
8 #define LCDCONTROL_LCDEN (1)
9 #define LCDCONTROL_LCDBPP(x) (((x) & 7) << 1)
10 #define LCDCONTROL_LCDTFT (1 << 5)
11
12 #define PL110_LCDTIMING0 (PVOID)0xE0020000
13 #define PL110_LCDTIMING1 (PVOID)0xE0020004
14 #define PL110_LCDTIMING2 (PVOID)0xE0020008
15 #define PL110_LCDUPBASE (PVOID)0xE0020010
16 #define PL110_LCDLPBASE (PVOID)0xE0020014
17 #define PL110_LCDCONTROL (PVOID)0xE0020018
18
19 #define READ_REGISTER_ULONG(r) (*(volatile ULONG * const)(r))
20 #define WRITE_REGISTER_ULONG(r, v) (*(volatile ULONG *)(r) = (v))
21
22 #define READ_REGISTER_USHORT(r) (*(volatile USHORT * const)(r))
23 #define WRITE_REGISTER_USHORT(r, v) (*(volatile USHORT *)(r) = (v))
24
25 PUSHORT VgaArmBase;
26 PHYSICAL_ADDRESS VgaPhysical;
27 BOOLEAN NextLine = FALSE;
28 UCHAR VidpTextColor = 0xF;
29 ULONG VidpCurrentX = 0;
30 ULONG VidpCurrentY = 0;
31 ULONG VidpScrollRegion[4] =
32 {
33 0,
34 0,
35 640 - 1,
36 480 - 1
37 };
38
39 typedef struct _VGA_COLOR
40 {
41 UCHAR Red;
42 UCHAR Green;
43 UCHAR Blue;
44 } VGA_COLOR;
45
46 VGA_COLOR VidpVga8To16BitTransform[16] =
47 {
48 {0x00, 0x00, 0x00}, // Black
49 {0x00, 0x00, 0x08}, // Blue
50 {0x00, 0x08, 0x00}, // Green
51 {0x00, 0x08, 0x08}, // Cyan
52 {0x08, 0x00, 0x00}, // Red
53 {0x08, 0x00, 0x08}, // Magenta
54 {0x0B, 0x0D, 0x0F}, // Brown
55 {0x10, 0x10, 0x10}, // Light Gray
56 {0x08, 0x08, 0x08}, // Dark Gray
57 {0x00, 0x00, 0x1F}, // Light Blue
58 {0x00, 0x1F, 0x00}, // Light Green
59 {0x00, 0x1F, 0x1F}, // Light Cyan
60 {0x1F, 0x00, 0x00}, // Light Red
61 {0x1F, 0x00, 0x1F}, // Light Magenta
62 {0x1F, 0x1F, 0x00}, // Yellow
63 {0x1F, 0x1F, 0x1F}, // White
64 };
65
66 /* PRIVATE FUNCTIONS *********************************************************/
67
68 USHORT
69 FORCEINLINE
70 VidpBuildColor(IN UCHAR Color)
71 {
72 UCHAR Red, Green, Blue;
73
74 //
75 // Extract color components
76 //
77 Red = VidpVga8To16BitTransform[Color].Red;
78 Green = VidpVga8To16BitTransform[Color].Green;
79 Blue = VidpVga8To16BitTransform[Color].Blue;
80
81 //
82 // Build the 16-bit color mask
83 //
84 return ((Red & 0x1F) << 11) | ((Green & 0x1F) << 6) | ((Blue & 0x1F));
85 }
86
87
88 VOID
89 FORCEINLINE
90 VidpSetPixel(IN ULONG Left,
91 IN ULONG Top,
92 IN UCHAR Color)
93 {
94 PUSHORT PixelPosition;
95
96 //
97 // Calculate the pixel position
98 //
99 PixelPosition = &VgaArmBase[Left + (Top * 640)];
100
101 //
102 // Set our color
103 //
104 WRITE_REGISTER_USHORT(PixelPosition, VidpBuildColor(Color));
105 }
106
107 VOID
108 NTAPI
109 DisplayCharacter(CHAR Character,
110 ULONG Left,
111 ULONG Top,
112 ULONG TextColor,
113 ULONG BackTextColor)
114 {
115 PUCHAR FontChar;
116 ULONG i, j, XOffset;
117
118 /* Get the font line for this character */
119 FontChar = &FontData[Character * 13 - Top];
120
121 /* Loop each pixel height */
122 i = 13;
123 do
124 {
125 /* Loop each pixel width */
126 j = 128;
127 XOffset = Left;
128 do
129 {
130 /* Check if we should draw this pixel */
131 if (FontChar[Top] & (UCHAR)j)
132 {
133 /* We do, use the given Text Color */
134 VidpSetPixel(XOffset, Top, (UCHAR)TextColor);
135 }
136 else if (BackTextColor < 16)
137 {
138 /* This is a background pixel. We're drawing it unless it's */
139 /* transparent. */
140 VidpSetPixel(XOffset, Top, (UCHAR)BackTextColor);
141 }
142
143 /* Increase X Offset */
144 XOffset++;
145 } while (j >>= 1);
146
147 /* Move to the next Y ordinate */
148 Top++;
149 } while (--i);
150 }
151
152 VOID
153 NTAPI
154 VgaScroll(ULONG Scroll)
155 {
156 ULONG Top, Offset;
157 PUSHORT SourceOffset, DestOffset;
158 PUSHORT i, j;
159
160 /* Set memory positions of the scroll */
161 SourceOffset = &VgaArmBase[(VidpScrollRegion[1] * 80) + (VidpScrollRegion[0] >> 3)];
162 DestOffset = &SourceOffset[Scroll * 80];
163
164 /* Save top and check if it's above the bottom */
165 Top = VidpScrollRegion[1];
166 if (Top > VidpScrollRegion[3]) return;
167
168 /* Start loop */
169 do
170 {
171 /* Set number of bytes to loop and start offset */
172 Offset = VidpScrollRegion[0] >> 3;
173 j = SourceOffset;
174
175 /* Check if this is part of the scroll region */
176 if (Offset <= (VidpScrollRegion[2] >> 3))
177 {
178 /* Update position */
179 i = (PUSHORT)(DestOffset - SourceOffset);
180
181 /* Loop the X axis */
182 do
183 {
184 /* Write value in the new position so that we can do the scroll */
185 WRITE_REGISTER_USHORT(j, READ_REGISTER_USHORT(j + (ULONG_PTR)i));
186
187 /* Move to the next memory location to write to */
188 j++;
189
190 /* Move to the next byte in the region */
191 Offset++;
192
193 /* Make sure we don't go past the scroll region */
194 } while (Offset <= (VidpScrollRegion[2] >> 3));
195 }
196
197 /* Move to the next line */
198 SourceOffset += 80;
199 DestOffset += 80;
200
201 /* Increase top */
202 Top++;
203
204 /* Make sure we don't go past the scroll region */
205 } while (Top <= VidpScrollRegion[3]);
206 }
207
208 VOID
209 NTAPI
210 PreserveRow(IN ULONG CurrentTop,
211 IN ULONG TopDelta,
212 IN BOOLEAN Direction)
213 {
214 PUSHORT Position1, Position2;
215 ULONG Count;
216
217 /* Check which way we're preserving */
218 if (Direction)
219 {
220 /* Calculate the position in memory for the row */
221 Position1 = &VgaArmBase[CurrentTop * 80];
222 Position2 = &VgaArmBase[0x9600];
223 }
224 else
225 {
226 /* Calculate the position in memory for the row */
227 Position1 = &VgaArmBase[0x9600];
228 Position2 = &VgaArmBase[CurrentTop * 80];
229 }
230
231 /* Set the count and make sure it's above 0 */
232 Count = TopDelta * 80;
233 if (Count)
234 {
235 /* Loop every pixel */
236 do
237 {
238 /* Write the data back on the other position */
239 WRITE_REGISTER_USHORT(Position1, READ_REGISTER_USHORT(Position2));
240
241 /* Increase both positions */
242 Position2++;
243 Position1++;
244 } while (--Count);
245 }
246 }
247
248 VOID
249 NTAPI
250 VidpInitializeDisplay(VOID)
251 {
252 //
253 // Set framebuffer address
254 //
255 WRITE_REGISTER_ULONG(PL110_LCDUPBASE, VgaPhysical.LowPart);
256 WRITE_REGISTER_ULONG(PL110_LCDLPBASE, VgaPhysical.LowPart);
257
258 //
259 // Initialize timings to 640x480
260 //
261 WRITE_REGISTER_ULONG(PL110_LCDTIMING0, LCDTIMING0_PPL(640));
262 WRITE_REGISTER_ULONG(PL110_LCDTIMING1, LCDTIMING1_LPP(480));
263
264 //
265 // Enable the LCD Display
266 //
267 WRITE_REGISTER_ULONG(PL110_LCDCONTROL,
268 LCDCONTROL_LCDEN |
269 LCDCONTROL_LCDTFT |
270 LCDCONTROL_LCDPWR |
271 LCDCONTROL_LCDBPP(4));
272 }
273
274 /* PUBLIC FUNCTIONS **********************************************************/
275
276 /*
277 * @implemented
278 */
279 BOOLEAN
280 NTAPI
281 VidInitialize(IN BOOLEAN SetMode)
282 {
283 DPRINT1("bv-arm v0.1\n");
284
285 //
286 // Allocate framebuffer
287 // 600kb works out to 640x480@16bpp
288 //
289 VgaPhysical.QuadPart = -1;
290 VgaArmBase = MmAllocateContiguousMemory(600 * 1024, VgaPhysical);
291 if (!VgaArmBase) return FALSE;
292
293 //
294 // Get physical address
295 //
296 VgaPhysical = MmGetPhysicalAddress(VgaArmBase);
297 if (!VgaPhysical.QuadPart) return FALSE;
298 DPRINT1("[BV-ARM] Frame Buffer @ 0x%p 0p%p\n", VgaArmBase, VgaPhysical.LowPart);
299
300 //
301 // Setup the display
302 //
303 VidpInitializeDisplay();
304
305 //
306 // We are done!
307 //
308 return TRUE;
309 }
310
311 /*
312 * @implemented
313 */
314 VOID
315 NTAPI
316 VidResetDisplay(IN BOOLEAN HalReset)
317 {
318 //
319 // Clear the current position
320 //
321 VidpCurrentX = 0;
322 VidpCurrentY = 0;
323
324 //
325 // Re-initialize the VGA Display
326 //
327 VidpInitializeDisplay();
328
329 //
330 // Re-initialize the palette and fill the screen black
331 //
332 //InitializePalette();
333 VidSolidColorFill(0, 0, 639, 479, 0);
334 }
335
336 /*
337 * @implemented
338 */
339 ULONG
340 NTAPI
341 VidSetTextColor(ULONG Color)
342 {
343 UCHAR OldColor;
344
345 //
346 // Save the old, set the new
347 //
348 OldColor = VidpTextColor;
349 VidpTextColor = Color;
350
351 //
352 // Return the old text color
353 //
354 return OldColor;
355 }
356
357 /*
358 * @implemented
359 */
360 VOID
361 NTAPI
362 VidDisplayStringXY(PUCHAR String,
363 ULONG Left,
364 ULONG Top,
365 BOOLEAN Transparent)
366 {
367 UNIMPLEMENTED;
368 while (TRUE);
369 }
370
371 /*
372 * @implemented
373 */
374 VOID
375 NTAPI
376 VidSetScrollRegion(ULONG x1,
377 ULONG y1,
378 ULONG x2,
379 ULONG y2)
380 {
381 /* Assert alignment */
382 ASSERT((x1 & 0x7) == 0);
383 ASSERT((x2 & 0x7) == 7);
384
385 /* Set Scroll Region */
386 VidpScrollRegion[0] = x1;
387 VidpScrollRegion[1] = y1;
388 VidpScrollRegion[2] = x2;
389 VidpScrollRegion[3] = y2;
390
391 /* Set current X and Y */
392 VidpCurrentX = x1;
393 VidpCurrentY = y1;
394 }
395
396 /*
397 * @implemented
398 */
399 VOID
400 NTAPI
401 VidCleanUp(VOID)
402 {
403 UNIMPLEMENTED;
404 while (TRUE);
405 }
406
407 /*
408 * @implemented
409 */
410 VOID
411 NTAPI
412 VidBufferToScreenBlt(IN PUCHAR Buffer,
413 IN ULONG Left,
414 IN ULONG Top,
415 IN ULONG Width,
416 IN ULONG Height,
417 IN ULONG Delta)
418 {
419 UNIMPLEMENTED;
420 while (TRUE);
421 }
422
423 /*
424 * @implemented
425 */
426 VOID
427 NTAPI
428 VidDisplayString(PUCHAR String)
429 {
430 ULONG TopDelta = 14;
431
432 /* Start looping the string */
433 while (*String)
434 {
435 /* Treat new-line separately */
436 if (*String == '\n')
437 {
438 /* Modify Y position */
439 VidpCurrentY += TopDelta;
440 if (VidpCurrentY >= VidpScrollRegion[3])
441 {
442 /* Scroll the view */
443 VgaScroll(TopDelta);
444 VidpCurrentY -= TopDelta;
445
446 /* Preserve row */
447 PreserveRow(VidpCurrentY, TopDelta, TRUE);
448 }
449
450 /* Update current X */
451 VidpCurrentX = VidpScrollRegion[0];
452
453 /* Preseve the current row */
454 PreserveRow(VidpCurrentY, TopDelta, FALSE);
455 }
456 else if (*String == '\r')
457 {
458 /* Update current X */
459 VidpCurrentX = VidpScrollRegion[0];
460
461 /* Check if we're being followed by a new line */
462 if (String[1] != '\n') NextLine = TRUE;
463 }
464 else
465 {
466 /* Check if we had a \n\r last time */
467 if (NextLine)
468 {
469 /* We did, preserve the current row */
470 PreserveRow(VidpCurrentY, TopDelta, TRUE);
471 NextLine = FALSE;
472 }
473
474 /* Display this character */
475 DisplayCharacter(*String,
476 VidpCurrentX,
477 VidpCurrentY,
478 VidpTextColor,
479 16);
480 VidpCurrentX += 8;
481
482 /* Check if we should scroll */
483 if (VidpCurrentX > VidpScrollRegion[2])
484 {
485 /* Update Y position and check if we should scroll it */
486 VidpCurrentY += TopDelta;
487 if (VidpCurrentY > VidpScrollRegion[3])
488 {
489 /* Do the scroll */
490 VgaScroll(TopDelta);
491 VidpCurrentY -= TopDelta;
492
493 /* Save the row */
494 PreserveRow(VidpCurrentY, TopDelta, TRUE);
495 }
496
497 /* Update X */
498 VidpCurrentX = VidpScrollRegion[0];
499 }
500 }
501
502 /* Get the next character */
503 String++;
504 }
505 }
506
507 /*
508 * @implemented
509 */
510 VOID
511 NTAPI
512 VidBitBlt(PUCHAR Buffer,
513 ULONG Left,
514 ULONG Top)
515 {
516 UNIMPLEMENTED;
517 //while (TRUE);
518 }
519
520 /*
521 * @implemented
522 */
523 VOID
524 NTAPI
525 VidScreenToBufferBlt(PUCHAR Buffer,
526 ULONG Left,
527 ULONG Top,
528 ULONG Width,
529 ULONG Height,
530 ULONG Delta)
531 {
532 UNIMPLEMENTED;
533 while (TRUE);
534 }
535
536 /*
537 * @implemented
538 */
539 VOID
540 NTAPI
541 VidSolidColorFill(IN ULONG Left,
542 IN ULONG Top,
543 IN ULONG Right,
544 IN ULONG Bottom,
545 IN UCHAR Color)
546 {
547 int y, x;
548
549 //
550 // Loop along the Y-axis
551 //
552 for (y = Top; y <= Bottom; y++)
553 {
554 //
555 // Loop along the X-axis
556 //
557 for (x = Left; x <= Right; x++)
558 {
559 //
560 // Draw the pixel
561 //
562 VidpSetPixel(x, y, Color);
563 }
564 }
565 }