xref: /reactos/drivers/base/bootvid/arm/bootvid.c (revision 8a978a17)
1 #include "precomp.h"
2 
3 #define NDEBUG
4 #include <debug.h>
5 
6 PUSHORT VgaArmBase;
7 PHYSICAL_ADDRESS VgaPhysical;
8 
9 /* PRIVATE FUNCTIONS *********************************************************/
10 
11 VOID
12 NTAPI
13 DisplayCharacter(
14     _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 = &VidpFontData[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 < BV_COLOR_NONE)
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 DoScroll(
60     _In_ ULONG Scroll)
61 {
62     ULONG Top, Offset;
63     PUSHORT SourceOffset, DestOffset;
64     PUSHORT i, j;
65 
66     /* Set memory positions of the scroll */
67     SourceOffset = &VgaArmBase[(VidpScrollRegion[1] * (SCREEN_WIDTH / 8)) + (VidpScrollRegion[0] >> 3)];
68     DestOffset = &SourceOffset[Scroll * (SCREEN_WIDTH / 8)];
69 
70     /* Start loop */
71     for (Top = VidpScrollRegion[1]; Top <= VidpScrollRegion[3]; ++Top)
72     {
73         /* Set number of bytes to loop and start offset */
74         Offset = VidpScrollRegion[0] >> 3;
75         j = SourceOffset;
76 
77         /* Check if this is part of the scroll region */
78         if (Offset <= (VidpScrollRegion[2] >> 3))
79         {
80             /* Update position */
81             i = (PUSHORT)(DestOffset - SourceOffset);
82 
83             /* Loop the X axis */
84             do
85             {
86                 /* Write value in the new position so that we can do the scroll */
87                 WRITE_REGISTER_USHORT(j, READ_REGISTER_USHORT(j + (ULONG_PTR)i));
88 
89                 /* Move to the next memory location to write to */
90                 j++;
91 
92                 /* Move to the next byte in the region */
93                 Offset++;
94 
95                 /* Make sure we don't go past the scroll region */
96             } while (Offset <= (VidpScrollRegion[2] >> 3));
97         }
98 
99         /* Move to the next line */
100         SourceOffset += (SCREEN_WIDTH / 8);
101         DestOffset += (SCREEN_WIDTH / 8);
102     }
103 }
104 
105 VOID
106 NTAPI
107 PreserveRow(
108     _In_ ULONG CurrentTop,
109     _In_ ULONG TopDelta,
110     _In_ BOOLEAN Restore)
111 {
112     PUSHORT Position1, Position2;
113     ULONG Count;
114 
115     /* Calculate the position in memory for the row */
116     if (Restore)
117     {
118         /* Restore the row by copying back the contents saved off-screen */
119         Position1 = &VgaArmBase[CurrentTop * (SCREEN_WIDTH / 8)];
120         Position2 = &VgaArmBase[SCREEN_HEIGHT * (SCREEN_WIDTH / 8)];
121     }
122     else
123     {
124         /* Preserve the row by saving its contents off-screen */
125         Position1 = &VgaArmBase[SCREEN_HEIGHT * (SCREEN_WIDTH / 8)];
126         Position2 = &VgaArmBase[CurrentTop * (SCREEN_WIDTH / 8)];
127     }
128 
129     /* Set the count and loop every pixel */
130     Count = TopDelta * (SCREEN_WIDTH / 8);
131     while (Count--)
132     {
133         /* Write the data back on the other position */
134         WRITE_REGISTER_USHORT(Position1, READ_REGISTER_USHORT(Position2));
135 
136         /* Increase both positions */
137         Position1++;
138         Position2++;
139     }
140 }
141 
142 VOID
143 NTAPI
144 VidpInitializeDisplay(VOID)
145 {
146     //
147     // Set framebuffer address
148     //
149     WRITE_REGISTER_ULONG(PL110_LCDUPBASE, VgaPhysical.LowPart);
150     WRITE_REGISTER_ULONG(PL110_LCDLPBASE, VgaPhysical.LowPart);
151 
152     //
153     // Initialize timings to 640x480
154     //
155     WRITE_REGISTER_ULONG(PL110_LCDTIMING0, LCDTIMING0_PPL(SCREEN_WIDTH));
156     WRITE_REGISTER_ULONG(PL110_LCDTIMING1, LCDTIMING1_LPP(SCREEN_HEIGHT));
157 
158     //
159     // Enable the LCD Display
160     //
161     WRITE_REGISTER_ULONG(PL110_LCDCONTROL,
162                          LCDCONTROL_LCDEN |
163                          LCDCONTROL_LCDTFT |
164                          LCDCONTROL_LCDPWR |
165                          LCDCONTROL_LCDBPP(4));
166 }
167 
168 VOID
169 NTAPI
170 InitPaletteWithTable(
171     _In_ PULONG Table,
172     _In_ ULONG Count)
173 {
174     UNIMPLEMENTED;
175 }
176 
177 /* PUBLIC FUNCTIONS **********************************************************/
178 
179 /*
180  * @implemented
181  */
182 BOOLEAN
183 NTAPI
184 VidInitialize(
185     _In_ BOOLEAN SetMode)
186 {
187     DPRINT1("bv-arm v0.1\n");
188 
189     //
190     // Allocate framebuffer
191     // 600kb works out to 640x480@16bpp
192     //
193     VgaPhysical.QuadPart = -1;
194     VgaArmBase = MmAllocateContiguousMemory(600 * 1024, VgaPhysical);
195     if (!VgaArmBase) return FALSE;
196 
197     //
198     // Get physical address
199     //
200     VgaPhysical = MmGetPhysicalAddress(VgaArmBase);
201     if (!VgaPhysical.QuadPart) return FALSE;
202     DPRINT1("[BV-ARM] Frame Buffer @ 0x%p 0p%p\n", VgaArmBase, VgaPhysical.LowPart);
203 
204     //
205     // Setup the display
206     //
207     VidpInitializeDisplay();
208 
209     //
210     // We are done!
211     //
212     return TRUE;
213 }
214 
215 /*
216  * @implemented
217  */
218 VOID
219 NTAPI
220 VidResetDisplay(
221     _In_ BOOLEAN HalReset)
222 {
223     //
224     // Clear the current position
225     //
226     VidpCurrentX = 0;
227     VidpCurrentY = 0;
228 
229     //
230     // Re-initialize the VGA Display
231     //
232     VidpInitializeDisplay();
233 
234     //
235     // Re-initialize the palette and fill the screen black
236     //
237     InitializePalette();
238     VidSolidColorFill(0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1, BV_COLOR_BLACK);
239 }
240 
241 /*
242  * @implemented
243  */
244 VOID
245 NTAPI
246 VidCleanUp(VOID)
247 {
248     UNIMPLEMENTED;
249     while (TRUE);
250 }
251 
252 /*
253  * @implemented
254  */
255 VOID
256 NTAPI
257 VidScreenToBufferBlt(
258     _Out_writes_bytes_(Delta * Height) PUCHAR Buffer,
259     _In_ ULONG Left,
260     _In_ ULONG Top,
261     _In_ ULONG Width,
262     _In_ ULONG Height,
263     _In_ ULONG Delta)
264 {
265     UNIMPLEMENTED;
266     while (TRUE);
267 }
268 
269 /*
270  * @implemented
271  */
272 VOID
273 NTAPI
274 VidSolidColorFill(
275     _In_ ULONG Left,
276     _In_ ULONG Top,
277     _In_ ULONG Right,
278     _In_ ULONG Bottom,
279     _In_ UCHAR Color)
280 {
281     int y, x;
282 
283     //
284     // Loop along the Y-axis
285     //
286     for (y = Top; y <= Bottom; y++)
287     {
288         //
289         // Loop along the X-axis
290         //
291         for (x = Left; x <= Right; x++)
292         {
293             //
294             // Draw the pixel
295             //
296             SetPixel(x, y, Color);
297         }
298     }
299 }
300