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