xref: /reactos/drivers/base/bootvid/arm/bootvid.c (revision e8c7597b)
1 /*
2  * PROJECT:     ReactOS Boot Video Driver for ARM devices
3  * LICENSE:     BSD - See COPYING.ARM in root directory
4  * PURPOSE:     Main file
5  * COPYRIGHT:   Copyright 2008 ReactOS Portable Systems Group <ros.arm@reactos.org>
6  */
7 
8 #include "precomp.h"
9 
10 #define NDEBUG
11 #include <debug.h>
12 
13 PUSHORT VgaArmBase;
14 PHYSICAL_ADDRESS VgaPhysical;
15 
16 /* PRIVATE FUNCTIONS *********************************************************/
17 
18 VOID
19 DisplayCharacter(
20     _In_ CHAR Character,
21     _In_ ULONG Left,
22     _In_ ULONG Top,
23     _In_ ULONG TextColor,
24     _In_ ULONG BackColor)
25 {
26     PUCHAR FontChar;
27     ULONG i, j, XOffset;
28 
29     /* Get the font line for this character */
30     FontChar = &VidpFontData[Character * BOOTCHAR_HEIGHT - Top];
31 
32     /* Loop each pixel height */
33     for (i = BOOTCHAR_HEIGHT; i > 0; --i)
34     {
35         /* Loop each pixel width */
36         XOffset = Left;
37         for (j = (1 << 7); j > 0; j >>= 1)
38         {
39             /* Check if we should draw this pixel */
40             if (FontChar[Top] & (UCHAR)j)
41             {
42                 /* We do, use the given Text Color */
43                 SetPixel(XOffset, Top, (UCHAR)TextColor);
44             }
45             else if (BackColor < BV_COLOR_NONE)
46             {
47                 /*
48                  * This is a background pixel. We're drawing it
49                  * unless it's transparent.
50                  */
51                 SetPixel(XOffset, Top, (UCHAR)BackColor);
52             }
53 
54             /* Increase X Offset */
55             XOffset++;
56         }
57 
58         /* Move to the next Y ordinate */
59         Top++;
60     }
61 }
62 
63 VOID
64 DoScroll(
65     _In_ ULONG Scroll)
66 {
67     ULONG Top, Offset;
68     PUSHORT SourceOffset, DestOffset;
69     PUSHORT i, j;
70 
71     /* Set memory positions of the scroll */
72     SourceOffset = &VgaArmBase[(VidpScrollRegion[1] * (SCREEN_WIDTH / 8)) + (VidpScrollRegion[0] >> 3)];
73     DestOffset = &SourceOffset[Scroll * (SCREEN_WIDTH / 8)];
74 
75     /* Start loop */
76     for (Top = VidpScrollRegion[1]; Top <= VidpScrollRegion[3]; ++Top)
77     {
78         /* Set number of bytes to loop and start offset */
79         Offset = VidpScrollRegion[0] >> 3;
80         j = SourceOffset;
81 
82         /* Check if this is part of the scroll region */
83         if (Offset <= (VidpScrollRegion[2] >> 3))
84         {
85             /* Update position */
86             i = (PUSHORT)(DestOffset - SourceOffset);
87 
88             /* Loop the X axis */
89             do
90             {
91                 /* Write value in the new position so that we can do the scroll */
92                 WRITE_REGISTER_USHORT(j, READ_REGISTER_USHORT(j + (ULONG_PTR)i));
93 
94                 /* Move to the next memory location to write to */
95                 j++;
96 
97                 /* Move to the next byte in the region */
98                 Offset++;
99 
100                 /* Make sure we don't go past the scroll region */
101             } while (Offset <= (VidpScrollRegion[2] >> 3));
102         }
103 
104         /* Move to the next line */
105         SourceOffset += (SCREEN_WIDTH / 8);
106         DestOffset += (SCREEN_WIDTH / 8);
107     }
108 }
109 
110 VOID
111 PreserveRow(
112     _In_ ULONG CurrentTop,
113     _In_ ULONG TopDelta,
114     _In_ BOOLEAN Restore)
115 {
116     PUSHORT Position1, Position2;
117     ULONG Count;
118 
119     /* Calculate the position in memory for the row */
120     if (Restore)
121     {
122         /* Restore the row by copying back the contents saved off-screen */
123         Position1 = &VgaArmBase[CurrentTop * (SCREEN_WIDTH / 8)];
124         Position2 = &VgaArmBase[SCREEN_HEIGHT * (SCREEN_WIDTH / 8)];
125     }
126     else
127     {
128         /* Preserve the row by saving its contents off-screen */
129         Position1 = &VgaArmBase[SCREEN_HEIGHT * (SCREEN_WIDTH / 8)];
130         Position2 = &VgaArmBase[CurrentTop * (SCREEN_WIDTH / 8)];
131     }
132 
133     /* Set the count and loop every pixel */
134     Count = TopDelta * (SCREEN_WIDTH / 8);
135     while (Count--)
136     {
137         /* Write the data back on the other position */
138         WRITE_REGISTER_USHORT(Position1, READ_REGISTER_USHORT(Position2));
139 
140         /* Increase both positions */
141         Position1++;
142         Position2++;
143     }
144 }
145 
146 VOID
147 VidpInitializeDisplay(VOID)
148 {
149     //
150     // Set framebuffer address
151     //
152     WRITE_REGISTER_ULONG(PL110_LCDUPBASE, VgaPhysical.LowPart);
153     WRITE_REGISTER_ULONG(PL110_LCDLPBASE, VgaPhysical.LowPart);
154 
155     //
156     // Initialize timings to 640x480
157     //
158     WRITE_REGISTER_ULONG(PL110_LCDTIMING0, LCDTIMING0_PPL(SCREEN_WIDTH));
159     WRITE_REGISTER_ULONG(PL110_LCDTIMING1, LCDTIMING1_LPP(SCREEN_HEIGHT));
160 
161     //
162     // Enable the LCD Display
163     //
164     WRITE_REGISTER_ULONG(PL110_LCDCONTROL,
165                          LCDCONTROL_LCDEN |
166                          LCDCONTROL_LCDTFT |
167                          LCDCONTROL_LCDPWR |
168                          LCDCONTROL_LCDBPP(4));
169 }
170 
171 VOID
172 InitPaletteWithTable(
173     _In_ PULONG Table,
174     _In_ ULONG Count)
175 {
176     UNIMPLEMENTED;
177 }
178 
179 /* PUBLIC FUNCTIONS **********************************************************/
180 
181 BOOLEAN
182 NTAPI
183 VidInitialize(
184     _In_ BOOLEAN SetMode)
185 {
186     DPRINT1("bv-arm v0.1\n");
187 
188     //
189     // Allocate framebuffer
190     // 600kb works out to 640x480@16bpp
191     //
192     VgaPhysical.QuadPart = -1;
193     VgaArmBase = MmAllocateContiguousMemory(600 * 1024, VgaPhysical);
194     if (!VgaArmBase) return FALSE;
195 
196     //
197     // Get physical address
198     //
199     VgaPhysical = MmGetPhysicalAddress(VgaArmBase);
200     if (!VgaPhysical.QuadPart) return FALSE;
201     DPRINT1("[BV-ARM] Frame Buffer @ 0x%p 0p%p\n", VgaArmBase, VgaPhysical.LowPart);
202 
203     //
204     // Setup the display
205     //
206     VidpInitializeDisplay();
207 
208     //
209     // We are done!
210     //
211     return TRUE;
212 }
213 
214 VOID
215 NTAPI
216 VidResetDisplay(
217     _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, BV_COLOR_BLACK);
235 }
236 
237 VOID
238 NTAPI
239 VidCleanUp(VOID)
240 {
241     UNIMPLEMENTED;
242     while (TRUE);
243 }
244 
245 VOID
246 NTAPI
247 VidScreenToBufferBlt(
248     _Out_writes_bytes_(Delta * Height) PUCHAR Buffer,
249     _In_ ULONG Left,
250     _In_ ULONG Top,
251     _In_ ULONG Width,
252     _In_ ULONG Height,
253     _In_ ULONG Delta)
254 {
255     UNIMPLEMENTED;
256     while (TRUE);
257 }
258 
259 VOID
260 NTAPI
261 VidSolidColorFill(
262     _In_ ULONG Left,
263     _In_ ULONG Top,
264     _In_ ULONG Right,
265     _In_ ULONG Bottom,
266     _In_ UCHAR Color)
267 {
268     int y, x;
269 
270     //
271     // Loop along the Y-axis
272     //
273     for (y = Top; y <= Bottom; y++)
274     {
275         //
276         // Loop along the X-axis
277         //
278         for (x = Left; x <= Right; x++)
279         {
280             //
281             // Draw the pixel
282             //
283             SetPixel(x, y, Color);
284         }
285     }
286 }
287