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 /* Preserve 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 } 563