xref: /reactos/drivers/base/bootvid/arm/bootvid.c (revision b8dd046e)
1 #include "precomp.h"
2 
3 #define NDEBUG
4 #include <debug.h>
5 
6 PUSHORT VgaArmBase;
7 PHYSICAL_ADDRESS VgaPhysical;
8 BOOLEAN ClearRow = FALSE;
9 
10 /* PRIVATE FUNCTIONS *********************************************************/
11 
12 VOID
13 NTAPI
14 DisplayCharacter(IN CHAR Character,
15                  IN ULONG Left,
16                  IN ULONG Top,
17                  IN ULONG TextColor,
18                  IN ULONG BackColor)
19 {
20     PUCHAR FontChar;
21     ULONG i, j, XOffset;
22 
23     /* Get the font line for this character */
24     FontChar = &FontData[Character * BOOTCHAR_HEIGHT - Top];
25 
26     /* Loop each pixel height */
27     for (i = BOOTCHAR_HEIGHT; i > 0; --i)
28     {
29         /* Loop each pixel width */
30         XOffset = Left;
31         for (j = (1 << 7); j > 0; j >>= 1)
32         {
33             /* Check if we should draw this pixel */
34             if (FontChar[Top] & (UCHAR)j)
35             {
36                 /* We do, use the given Text Color */
37                 SetPixel(XOffset, Top, (UCHAR)TextColor);
38             }
39             else if (BackColor < 16)
40             {
41                 /*
42                  * This is a background pixel. We're drawing it
43                  * unless it's transparent.
44                  */
45                 SetPixel(XOffset, Top, (UCHAR)BackColor);
46             }
47 
48             /* Increase X Offset */
49             XOffset++;
50         }
51 
52         /* Move to the next Y ordinate */
53         Top++;
54     }
55 }
56 
57 VOID
58 NTAPI
59 VgaScroll(IN ULONG Scroll)
60 {
61     ULONG Top, Offset;
62     PUSHORT SourceOffset, DestOffset;
63     PUSHORT i, j;
64 
65     /* Set memory positions of the scroll */
66     SourceOffset = &VgaArmBase[(VidpScrollRegion[1] * (SCREEN_WIDTH / 8)) + (VidpScrollRegion[0] >> 3)];
67     DestOffset = &SourceOffset[Scroll * (SCREEN_WIDTH / 8)];
68 
69     /* Start loop */
70     for (Top = VidpScrollRegion[1]; Top <= VidpScrollRegion[3]; ++Top)
71     {
72         /* Set number of bytes to loop and start offset */
73         Offset = VidpScrollRegion[0] >> 3;
74         j = SourceOffset;
75 
76         /* Check if this is part of the scroll region */
77         if (Offset <= (VidpScrollRegion[2] >> 3))
78         {
79             /* Update position */
80             i = (PUSHORT)(DestOffset - SourceOffset);
81 
82             /* Loop the X axis */
83             do
84             {
85                 /* Write value in the new position so that we can do the scroll */
86                 WRITE_REGISTER_USHORT(j, READ_REGISTER_USHORT(j + (ULONG_PTR)i));
87 
88                 /* Move to the next memory location to write to */
89                 j++;
90 
91                 /* Move to the next byte in the region */
92                 Offset++;
93 
94                 /* Make sure we don't go past the scroll region */
95             } while (Offset <= (VidpScrollRegion[2] >> 3));
96         }
97 
98         /* Move to the next line */
99         SourceOffset += (SCREEN_WIDTH / 8);
100         DestOffset += (SCREEN_WIDTH / 8);
101     }
102 }
103 
104 VOID
105 NTAPI
106 PreserveRow(IN ULONG CurrentTop,
107             IN ULONG TopDelta,
108             IN BOOLEAN Restore)
109 {
110     PUSHORT Position1, Position2;
111     ULONG Count;
112 
113     /* Calculate the position in memory for the row */
114     if (Restore)
115     {
116         /* Restore the row by copying back the contents saved off-screen */
117         Position1 = &VgaArmBase[CurrentTop * (SCREEN_WIDTH / 8)];
118         Position2 = &VgaArmBase[SCREEN_HEIGHT * (SCREEN_WIDTH / 8)];
119     }
120     else
121     {
122         /* Preserve the row by saving its contents off-screen */
123         Position1 = &VgaArmBase[SCREEN_HEIGHT * (SCREEN_WIDTH / 8)];
124         Position2 = &VgaArmBase[CurrentTop * (SCREEN_WIDTH / 8)];
125     }
126 
127     /* Set the count and loop every pixel */
128     Count = TopDelta * (SCREEN_WIDTH / 8);
129     while (Count--)
130     {
131         /* Write the data back on the other position */
132         WRITE_REGISTER_USHORT(Position1, READ_REGISTER_USHORT(Position2));
133 
134         /* Increase both positions */
135         Position1++;
136         Position2++;
137     }
138 }
139 
140 VOID
141 NTAPI
142 VidpInitializeDisplay(VOID)
143 {
144     //
145     // Set framebuffer address
146     //
147     WRITE_REGISTER_ULONG(PL110_LCDUPBASE, VgaPhysical.LowPart);
148     WRITE_REGISTER_ULONG(PL110_LCDLPBASE, VgaPhysical.LowPart);
149 
150     //
151     // Initialize timings to 640x480
152     //
153     WRITE_REGISTER_ULONG(PL110_LCDTIMING0, LCDTIMING0_PPL(SCREEN_WIDTH));
154     WRITE_REGISTER_ULONG(PL110_LCDTIMING1, LCDTIMING1_LPP(SCREEN_HEIGHT));
155 
156     //
157     // Enable the LCD Display
158     //
159     WRITE_REGISTER_ULONG(PL110_LCDCONTROL,
160                          LCDCONTROL_LCDEN |
161                          LCDCONTROL_LCDTFT |
162                          LCDCONTROL_LCDPWR |
163                          LCDCONTROL_LCDBPP(4));
164 }
165 
166 VOID
167 NTAPI
168 InitPaletteWithTable(
169     _In_ PULONG Table,
170     _In_ ULONG Count)
171 {
172     UNIMPLEMENTED;
173 }
174 
175 /* PUBLIC FUNCTIONS **********************************************************/
176 
177 /*
178  * @implemented
179  */
180 BOOLEAN
181 NTAPI
182 VidInitialize(IN BOOLEAN SetMode)
183 {
184     DPRINT1("bv-arm v0.1\n");
185 
186     //
187     // Allocate framebuffer
188     // 600kb works out to 640x480@16bpp
189     //
190     VgaPhysical.QuadPart = -1;
191     VgaArmBase = MmAllocateContiguousMemory(600 * 1024, VgaPhysical);
192     if (!VgaArmBase) return FALSE;
193 
194     //
195     // Get physical address
196     //
197     VgaPhysical = MmGetPhysicalAddress(VgaArmBase);
198     if (!VgaPhysical.QuadPart) return FALSE;
199     DPRINT1("[BV-ARM] Frame Buffer @ 0x%p 0p%p\n", VgaArmBase, VgaPhysical.LowPart);
200 
201     //
202     // Setup the display
203     //
204     VidpInitializeDisplay();
205 
206     //
207     // We are done!
208     //
209     return TRUE;
210 }
211 
212 /*
213  * @implemented
214  */
215 VOID
216 NTAPI
217 VidResetDisplay(IN BOOLEAN HalReset)
218 {
219     //
220     // Clear the current position
221     //
222     VidpCurrentX = 0;
223     VidpCurrentY = 0;
224 
225     //
226     // Re-initialize the VGA Display
227     //
228     VidpInitializeDisplay();
229 
230     //
231     // Re-initialize the palette and fill the screen black
232     //
233     //InitializePalette();
234     VidSolidColorFill(0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1, 0);
235 }
236 
237 /*
238  * @implemented
239  */
240 ULONG
241 NTAPI
242 VidSetTextColor(IN ULONG Color)
243 {
244     UCHAR OldColor;
245 
246     //
247     // Save the old, set the new
248     //
249     OldColor = VidpTextColor;
250     VidpTextColor = Color;
251 
252     //
253     // Return the old text color
254     //
255     return OldColor;
256 }
257 
258 /*
259  * @implemented
260  */
261 VOID
262 NTAPI
263 VidCleanUp(VOID)
264 {
265     UNIMPLEMENTED;
266     while (TRUE);
267 }
268 
269 /*
270  * @implemented
271  */
272 VOID
273 NTAPI
274 VidDisplayString(IN PUCHAR String)
275 {
276     ULONG TopDelta = BOOTCHAR_HEIGHT + 1;
277 
278     /* Start looping the string */
279     for (; *String; ++String)
280     {
281         /* Treat new-line separately */
282         if (*String == '\n')
283         {
284             /* Modify Y position */
285             VidpCurrentY += TopDelta;
286             if (VidpCurrentY + TopDelta - 1 > VidpScrollRegion[3])
287             {
288                 /* Scroll the view and clear the current row */
289                 VgaScroll(TopDelta);
290                 VidpCurrentY -= TopDelta;
291                 PreserveRow(VidpCurrentY, TopDelta, TRUE);
292             }
293             else
294             {
295                 /* Preserve the current row */
296                 PreserveRow(VidpCurrentY, TopDelta, FALSE);
297             }
298 
299             /* Update current X */
300             VidpCurrentX = VidpScrollRegion[0];
301 
302             /* No need to clear this row */
303             ClearRow = FALSE;
304         }
305         else if (*String == '\r')
306         {
307             /* Update current X */
308             VidpCurrentX = VidpScrollRegion[0];
309 
310             /* If a new-line does not follow we will clear the current row */
311             if (String[1] != '\n') ClearRow = TRUE;
312         }
313         else
314         {
315             /* Clear the current row if we had a return-carriage without a new-line */
316             if (ClearRow)
317             {
318                 PreserveRow(VidpCurrentY, TopDelta, TRUE);
319                 ClearRow = FALSE;
320             }
321 
322             /* Display this character */
323             DisplayCharacter(*String,
324                              VidpCurrentX,
325                              VidpCurrentY,
326                              VidpTextColor,
327                              16);
328             VidpCurrentX += 8;
329 
330             /* Check if we should scroll */
331             if (VidpCurrentX + 7 > VidpScrollRegion[2])
332             {
333                 /* Update Y position and check if we should scroll it */
334                 VidpCurrentY += TopDelta;
335                 if (VidpCurrentY + TopDelta - 1 > VidpScrollRegion[3])
336                 {
337                     /* Scroll the view and clear the current row */
338                     VgaScroll(TopDelta);
339                     VidpCurrentY -= TopDelta;
340                     PreserveRow(VidpCurrentY, TopDelta, TRUE);
341                 }
342                 else
343                 {
344                     /* Preserve the current row */
345                     PreserveRow(VidpCurrentY, TopDelta, FALSE);
346                 }
347 
348                 /* Update current X */
349                 VidpCurrentX = VidpScrollRegion[0];
350             }
351         }
352     }
353 }
354 
355 /*
356  * @implemented
357  */
358 VOID
359 NTAPI
360 VidScreenToBufferBlt(OUT PUCHAR Buffer,
361                      IN ULONG Left,
362                      IN ULONG Top,
363                      IN ULONG Width,
364                      IN ULONG Height,
365                      IN ULONG Delta)
366 {
367     UNIMPLEMENTED;
368     while (TRUE);
369 }
370 
371 /*
372  * @implemented
373  */
374 VOID
375 NTAPI
376 VidSolidColorFill(IN ULONG Left,
377                   IN ULONG Top,
378                   IN ULONG Right,
379                   IN ULONG Bottom,
380                   IN UCHAR Color)
381 {
382     int y, x;
383 
384     //
385     // Loop along the Y-axis
386     //
387     for (y = Top; y <= Bottom; y++)
388     {
389         //
390         // Loop along the X-axis
391         //
392         for (x = Left; x <= Right; x++)
393         {
394             //
395             // Draw the pixel
396             //
397             SetPixel(x, y, Color);
398         }
399     }
400 }
401