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)
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
20 #define READ_REGISTER_ULONG(r) (*(volatile ULONG * const)(r))
21 #define WRITE_REGISTER_ULONG(r, v) (*(volatile ULONG *)(r) = (v))
23 #define READ_REGISTER_USHORT(r) (*(volatile USHORT * const)(r))
24 #define WRITE_REGISTER_USHORT(r, v) (*(volatile USHORT *)(r) = (v))
27 PHYSICAL_ADDRESS VgaPhysical
;
28 BOOLEAN NextLine
= FALSE
;
29 UCHAR VidpTextColor
= 0xF;
30 ULONG VidpCurrentX
= 0;
31 ULONG VidpCurrentY
= 0;
32 ULONG VidpScrollRegion
[4] =
40 typedef struct _VGA_COLOR
47 VGA_COLOR VidpVga8To16BitTransform
[16] =
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
67 /* PRIVATE FUNCTIONS *********************************************************/
71 VidpBuildColor(IN UCHAR Color
)
73 UCHAR Red
, Green
, Blue
;
76 // Extract color components
78 Red
= VidpVga8To16BitTransform
[Color
].Red
;
79 Green
= VidpVga8To16BitTransform
[Color
].Green
;
80 Blue
= VidpVga8To16BitTransform
[Color
].Blue
;
83 // Build the 16-bit color mask
85 return ((Red
& 0x1F) << 11) | ((Green
& 0x1F) << 6) | ((Blue
& 0x1F));
91 VidpSetPixel(IN ULONG Left
,
95 PUSHORT PixelPosition
;
98 // Calculate the pixel position
100 PixelPosition
= &VgaArmBase
[Left
+ (Top
* 640)];
105 WRITE_REGISTER_USHORT(PixelPosition
, VidpBuildColor(Color
));
110 DisplayCharacter(IN CHAR Character
,
114 IN ULONG BackTextColor
)
119 /* Get the font line for this character */
120 FontChar
= &FontData
[Character
* 13 - Top
];
122 /* Loop each pixel height */
126 /* Loop each pixel width */
131 /* Check if we should draw this pixel */
132 if (FontChar
[Top
] & (UCHAR
)j
)
134 /* We do, use the given Text Color */
135 VidpSetPixel(XOffset
, Top
, (UCHAR
)TextColor
);
137 else if (BackTextColor
< 16)
139 /* This is a background pixel. We're drawing it unless it's */
141 VidpSetPixel(XOffset
, Top
, (UCHAR
)BackTextColor
);
144 /* Increase X Offset */
148 /* Move to the next Y ordinate */
155 VgaScroll(IN ULONG Scroll
)
158 PUSHORT SourceOffset
, DestOffset
;
161 /* Set memory positions of the scroll */
162 SourceOffset
= &VgaArmBase
[(VidpScrollRegion
[1] * 80) + (VidpScrollRegion
[0] >> 3)];
163 DestOffset
= &SourceOffset
[Scroll
* 80];
165 /* Save top and check if it's above the bottom */
166 Top
= VidpScrollRegion
[1];
167 if (Top
> VidpScrollRegion
[3]) return;
172 /* Set number of bytes to loop and start offset */
173 Offset
= VidpScrollRegion
[0] >> 3;
176 /* Check if this is part of the scroll region */
177 if (Offset
<= (VidpScrollRegion
[2] >> 3))
179 /* Update position */
180 i
= (PUSHORT
)(DestOffset
- SourceOffset
);
182 /* Loop the X axis */
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
));
188 /* Move to the next memory location to write to */
191 /* Move to the next byte in the region */
194 /* Make sure we don't go past the scroll region */
195 } while (Offset
<= (VidpScrollRegion
[2] >> 3));
198 /* Move to the next line */
205 /* Make sure we don't go past the scroll region */
206 } while (Top
<= VidpScrollRegion
[3]);
211 PreserveRow(IN ULONG CurrentTop
,
213 IN BOOLEAN Direction
)
215 PUSHORT Position1
, Position2
;
218 /* Check which way we're preserving */
221 /* Calculate the position in memory for the row */
222 Position1
= &VgaArmBase
[CurrentTop
* 80];
223 Position2
= &VgaArmBase
[0x9600];
227 /* Calculate the position in memory for the row */
228 Position1
= &VgaArmBase
[0x9600];
229 Position2
= &VgaArmBase
[CurrentTop
* 80];
232 /* Set the count and loop every pixel */
233 Count
= TopDelta
* 80;
236 /* Write the data back on the other position */
237 WRITE_REGISTER_USHORT(Position1
, READ_REGISTER_USHORT(Position2
));
239 /* Increase both positions */
247 VidpInitializeDisplay(VOID
)
250 // Set framebuffer address
252 WRITE_REGISTER_ULONG(PL110_LCDUPBASE
, VgaPhysical
.LowPart
);
253 WRITE_REGISTER_ULONG(PL110_LCDLPBASE
, VgaPhysical
.LowPart
);
256 // Initialize timings to 640x480
258 WRITE_REGISTER_ULONG(PL110_LCDTIMING0
, LCDTIMING0_PPL(640));
259 WRITE_REGISTER_ULONG(PL110_LCDTIMING1
, LCDTIMING1_LPP(480));
262 // Enable the LCD Display
264 WRITE_REGISTER_ULONG(PL110_LCDCONTROL
,
268 LCDCONTROL_LCDBPP(4));
271 /* PUBLIC FUNCTIONS **********************************************************/
278 VidInitialize(IN BOOLEAN SetMode
)
280 DPRINT1("bv-arm v0.1\n");
283 // Allocate framebuffer
284 // 600kb works out to 640x480@16bpp
286 VgaPhysical
.QuadPart
= -1;
287 VgaArmBase
= MmAllocateContiguousMemory(600 * 1024, VgaPhysical
);
288 if (!VgaArmBase
) return FALSE
;
291 // Get physical address
293 VgaPhysical
= MmGetPhysicalAddress(VgaArmBase
);
294 if (!VgaPhysical
.QuadPart
) return FALSE
;
295 DPRINT1("[BV-ARM] Frame Buffer @ 0x%p 0p%p\n", VgaArmBase
, VgaPhysical
.LowPart
);
300 VidpInitializeDisplay();
313 VidResetDisplay(IN BOOLEAN HalReset
)
316 // Clear the current position
322 // Re-initialize the VGA Display
324 VidpInitializeDisplay();
327 // Re-initialize the palette and fill the screen black
329 //InitializePalette();
330 VidSolidColorFill(0, 0, 639, 479, 0);
338 VidSetTextColor(IN ULONG Color
)
343 // Save the old, set the new
345 OldColor
= VidpTextColor
;
346 VidpTextColor
= Color
;
349 // Return the old text color
359 VidDisplayStringXY(IN PUCHAR String
,
362 IN BOOLEAN Transparent
)
373 VidSetScrollRegion(IN ULONG Left
,
378 /* Assert alignment */
379 ASSERT((Left
& 0x7) == 0);
380 ASSERT((Right
& 0x7) == 7);
382 /* Set Scroll Region */
383 VidpScrollRegion
[0] = Left
;
384 VidpScrollRegion
[1] = Top
;
385 VidpScrollRegion
[2] = Right
;
386 VidpScrollRegion
[3] = Bottom
;
388 /* Set current X and Y */
409 VidBufferToScreenBlt(IN PUCHAR Buffer
,
425 VidDisplayString(IN PUCHAR String
)
429 /* Start looping the string */
432 /* Treat new-line separately */
435 /* Modify Y position */
436 VidpCurrentY
+= TopDelta
;
437 if (VidpCurrentY
>= VidpScrollRegion
[3])
439 /* Scroll the view */
441 VidpCurrentY
-= TopDelta
;
444 PreserveRow(VidpCurrentY
, TopDelta
, TRUE
);
447 /* Update current X */
448 VidpCurrentX
= VidpScrollRegion
[0];
450 /* Preseve the current row */
451 PreserveRow(VidpCurrentY
, TopDelta
, FALSE
);
453 else if (*String
== '\r')
455 /* Update current X */
456 VidpCurrentX
= VidpScrollRegion
[0];
458 /* Check if we're being followed by a new line */
459 if (String
[1] != '\n') NextLine
= TRUE
;
463 /* Check if we had a \n\r last time */
466 /* We did, preserve the current row */
467 PreserveRow(VidpCurrentY
, TopDelta
, TRUE
);
471 /* Display this character */
472 DisplayCharacter(*String
,
479 /* Check if we should scroll */
480 if (VidpCurrentX
> VidpScrollRegion
[2])
482 /* Update Y position and check if we should scroll it */
483 VidpCurrentY
+= TopDelta
;
484 if (VidpCurrentY
> VidpScrollRegion
[3])
488 VidpCurrentY
-= TopDelta
;
491 PreserveRow(VidpCurrentY
, TopDelta
, TRUE
);
495 VidpCurrentX
= VidpScrollRegion
[0];
499 /* Get the next character */
509 VidBitBlt(IN PUCHAR Buffer
,
522 VidScreenToBufferBlt(IN PUCHAR Buffer
,
538 VidSolidColorFill(IN ULONG Left
,
547 // Loop along the Y-axis
549 for (y
= Top
; y
<= Bottom
; y
++)
552 // Loop along the X-axis
554 for (x
= Left
; x
<= Right
; x
++)
559 VidpSetPixel(x
, y
, Color
);