1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS kernel 4 * FILE: services/dd/blue/blue.c 5 * PURPOSE: Console (blue screen) device driver 6 * PROGRAMMER: Eric Kohl 7 * UPDATE HISTORY: 8 * ??? Created 9 */ 10 11 /* INCLUDES ******************************************************************/ 12 13 #include "blue.h" 14 15 #define NDEBUG 16 #include <debug.h> 17 18 // ROS Internal. Please deprecate. 19 NTHALAPI 20 BOOLEAN 21 NTAPI 22 HalQueryDisplayOwnership( 23 VOID 24 ); 25 26 /* NOTES ******************************************************************/ 27 /* 28 * [[character][attribute]][[character][attribute]].... 29 */ 30 31 32 /* TYPEDEFS ***************************************************************/ 33 34 typedef struct _DEVICE_EXTENSION 35 { 36 PUCHAR VideoMemory; /* Pointer to video memory */ 37 ULONG CursorSize; 38 INT CursorVisible; 39 USHORT CharAttribute; 40 ULONG Mode; 41 UCHAR ScanLines; /* Height of a text line */ 42 USHORT Rows; /* Number of rows */ 43 USHORT Columns; /* Number of columns */ 44 } DEVICE_EXTENSION, *PDEVICE_EXTENSION; 45 46 typedef struct _VGA_REGISTERS 47 { 48 UCHAR CRT[24]; 49 UCHAR Attribute[21]; 50 UCHAR Graphics[9]; 51 UCHAR Sequencer[5]; 52 UCHAR Misc; 53 } VGA_REGISTERS, *PVGA_REGISTERS; 54 55 static const VGA_REGISTERS VidpMode3Regs = 56 { 57 /* CRT Controller Registers */ 58 {0x5F, 0x4F, 0x50, 0x82, 0x55, 0x81, 0xBF, 0x1F, 0x00, 0x47, 0x1E, 0x00, 59 0x00, 0x00, 0x05, 0xF0, 0x9C, 0x8E, 0x8F, 0x28, 0x1F, 0x96, 0xB9, 0xA3}, 60 /* Attribute Controller Registers */ 61 {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B, 62 0x3C, 0x3D, 0x3E, 0x3F, 0x0C, 0x00, 0x0F, 0x08, 0x00}, 63 /* Graphics Controller Registers */ 64 {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x00, 0xFF}, 65 /* Sequencer Registers */ 66 {0x03, 0x00, 0x03, 0x00, 0x02}, 67 /* Misc Output Register */ 68 0x67 69 }; 70 71 static const UCHAR DefaultPalette[] = 72 { 73 0, 0, 0, 74 0, 0, 0xC0, 75 0, 0xC0, 0, 76 0, 0xC0, 0xC0, 77 0xC0, 0, 0, 78 0xC0, 0, 0xC0, 79 0xC0, 0xC0, 0, 80 0xC0, 0xC0, 0xC0, 81 0x80, 0x80, 0x80, 82 0, 0, 0xFF, 83 0, 0xFF, 0, 84 0, 0xFF, 0xFF, 85 0xFF, 0, 0, 86 0xFF, 0, 0xFF, 87 0xFF, 0xFF, 0, 88 0xFF, 0xFF, 0xFF 89 }; 90 91 /* FUNCTIONS **************************************************************/ 92 93 static VOID FASTCALL 94 ScrSetRegisters(const VGA_REGISTERS *Registers) 95 { 96 UINT32 i; 97 98 /* Update misc output register */ 99 WRITE_PORT_UCHAR(MISC, Registers->Misc); 100 101 /* Synchronous reset on */ 102 WRITE_PORT_UCHAR(SEQ, 0x00); 103 WRITE_PORT_UCHAR(SEQDATA, 0x01); 104 105 /* Write sequencer registers */ 106 for (i = 1; i < sizeof(Registers->Sequencer); i++) 107 { 108 WRITE_PORT_UCHAR(SEQ, i); 109 WRITE_PORT_UCHAR(SEQDATA, Registers->Sequencer[i]); 110 } 111 112 /* Synchronous reset off */ 113 WRITE_PORT_UCHAR(SEQ, 0x00); 114 WRITE_PORT_UCHAR(SEQDATA, 0x03); 115 116 /* Deprotect CRT registers 0-7 */ 117 WRITE_PORT_UCHAR(CRTC, 0x11); 118 WRITE_PORT_UCHAR(CRTCDATA, Registers->CRT[0x11] & 0x7f); 119 120 /* Write CRT registers */ 121 for (i = 0; i < sizeof(Registers->CRT); i++) 122 { 123 WRITE_PORT_UCHAR(CRTC, i); 124 WRITE_PORT_UCHAR(CRTCDATA, Registers->CRT[i]); 125 } 126 127 /* Write graphics controller registers */ 128 for (i = 0; i < sizeof(Registers->Graphics); i++) 129 { 130 WRITE_PORT_UCHAR(GRAPHICS, i); 131 WRITE_PORT_UCHAR(GRAPHICSDATA, Registers->Graphics[i]); 132 } 133 134 /* Write attribute controller registers */ 135 for (i = 0; i < sizeof(Registers->Attribute); i++) 136 { 137 READ_PORT_UCHAR(STATUS); 138 WRITE_PORT_UCHAR(ATTRIB, i); 139 WRITE_PORT_UCHAR(ATTRIB, Registers->Attribute[i]); 140 } 141 142 /* Set the PEL mask. */ 143 WRITE_PORT_UCHAR(PELMASK, 0xff); 144 } 145 146 static VOID FASTCALL 147 ScrAcquireOwnership(PDEVICE_EXTENSION DeviceExtension) 148 { 149 unsigned int offset; 150 UCHAR data, value; 151 ULONG Index; 152 153 ScrSetRegisters(&VidpMode3Regs); 154 155 /* Disable screen and enable palette access. */ 156 READ_PORT_UCHAR(STATUS); 157 WRITE_PORT_UCHAR(ATTRIB, 0x00); 158 159 for (Index = 0; Index < sizeof(DefaultPalette) / 3; Index++) 160 { 161 WRITE_PORT_UCHAR(PELINDEX, Index); 162 WRITE_PORT_UCHAR(PELDATA, DefaultPalette[Index * 3] >> 2); 163 WRITE_PORT_UCHAR(PELDATA, DefaultPalette[Index * 3 + 1] >> 2); 164 WRITE_PORT_UCHAR(PELDATA, DefaultPalette[Index * 3 + 2] >> 2); 165 } 166 167 /* Enable screen and disable palette access. */ 168 READ_PORT_UCHAR(STATUS); 169 WRITE_PORT_UCHAR(ATTRIB, 0x20); 170 171 /* get current output position */ 172 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO); 173 offset = READ_PORT_UCHAR (CRTC_DATA); 174 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI); 175 offset += (READ_PORT_UCHAR (CRTC_DATA) << 8); 176 177 /* switch blinking characters off */ 178 READ_PORT_UCHAR (ATTRC_INPST1); 179 value = READ_PORT_UCHAR (ATTRC_WRITEREG); 180 WRITE_PORT_UCHAR (ATTRC_WRITEREG, 0x10); 181 data = READ_PORT_UCHAR (ATTRC_READREG); 182 data = data & ~0x08; 183 WRITE_PORT_UCHAR (ATTRC_WRITEREG, data); 184 WRITE_PORT_UCHAR (ATTRC_WRITEREG, value); 185 READ_PORT_UCHAR (ATTRC_INPST1); 186 187 /* read screen information from crt controller */ 188 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_COLUMNS); 189 DeviceExtension->Columns = READ_PORT_UCHAR (CRTC_DATA) + 1; 190 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_ROWS); 191 DeviceExtension->Rows = READ_PORT_UCHAR (CRTC_DATA); 192 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_OVERFLOW); 193 data = READ_PORT_UCHAR (CRTC_DATA); 194 DeviceExtension->Rows |= (((data & 0x02) << 7) | ((data & 0x40) << 3)); 195 DeviceExtension->Rows++; 196 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_SCANLINES); 197 DeviceExtension->ScanLines = (READ_PORT_UCHAR (CRTC_DATA) & 0x1F) + 1; 198 199 /* show blinking cursor */ 200 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORSTART); 201 WRITE_PORT_UCHAR (CRTC_DATA, (DeviceExtension->ScanLines - 1) & 0x1F); 202 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSOREND); 203 data = READ_PORT_UCHAR (CRTC_DATA) & 0xE0; 204 WRITE_PORT_UCHAR (CRTC_DATA, 205 data | ((DeviceExtension->ScanLines - 1) & 0x1F)); 206 207 /* calculate number of text rows */ 208 DeviceExtension->Rows = 209 DeviceExtension->Rows / DeviceExtension->ScanLines; 210 #ifdef BOCHS_30ROWS 211 DeviceExtension->Rows = 30; 212 #endif 213 214 DPRINT ("%d Columns %d Rows %d Scanlines\n", 215 DeviceExtension->Columns, 216 DeviceExtension->Rows, 217 DeviceExtension->ScanLines); 218 } 219 220 NTSTATUS NTAPI 221 DriverEntry (PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath); 222 223 static DRIVER_DISPATCH ScrCreate; 224 static NTSTATUS NTAPI 225 ScrCreate(PDEVICE_OBJECT DeviceObject, 226 PIRP Irp) 227 { 228 PDEVICE_EXTENSION DeviceExtension; 229 PHYSICAL_ADDRESS BaseAddress; 230 NTSTATUS Status; 231 232 DeviceExtension = DeviceObject->DeviceExtension; 233 234 if (!InbvCheckDisplayOwnership()) 235 { 236 ScrAcquireOwnership(DeviceExtension); 237 238 /* get pointer to video memory */ 239 BaseAddress.QuadPart = VIDMEM_BASE; 240 DeviceExtension->VideoMemory = 241 (PUCHAR)MmMapIoSpace (BaseAddress, DeviceExtension->Rows * DeviceExtension->Columns * 2, MmNonCached); 242 } 243 else 244 { 245 /* store dummy values here */ 246 DeviceExtension->Columns = 1; 247 DeviceExtension->Rows = 1; 248 DeviceExtension->ScanLines = 1; 249 } 250 251 DeviceExtension->CursorSize = 5; /* FIXME: value correct?? */ 252 DeviceExtension->CursorVisible = TRUE; 253 254 /* more initialization */ 255 DeviceExtension->CharAttribute = 0x17; /* light grey on blue */ 256 DeviceExtension->Mode = ENABLE_PROCESSED_OUTPUT | 257 ENABLE_WRAP_AT_EOL_OUTPUT; 258 259 Status = STATUS_SUCCESS; 260 261 Irp->IoStatus.Status = Status; 262 IoCompleteRequest (Irp, IO_NO_INCREMENT); 263 264 return (Status); 265 } 266 267 static DRIVER_DISPATCH ScrWrite; 268 static NTSTATUS NTAPI 269 ScrWrite(PDEVICE_OBJECT DeviceObject, 270 PIRP Irp) 271 { 272 PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation (Irp); 273 PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; 274 NTSTATUS Status; 275 char *pch = Irp->UserBuffer; 276 PUCHAR vidmem; 277 unsigned int i; 278 int j, offset; 279 int cursorx, cursory; 280 int rows, columns; 281 int processed = DeviceExtension->Mode & ENABLE_PROCESSED_OUTPUT; 282 283 if (InbvCheckDisplayOwnership()) 284 { 285 /* Display is in graphics mode, we're not allowed to touch it */ 286 Status = STATUS_SUCCESS; 287 288 Irp->IoStatus.Status = Status; 289 IoCompleteRequest (Irp, IO_NO_INCREMENT); 290 291 return Status; 292 } 293 294 vidmem = DeviceExtension->VideoMemory; 295 rows = DeviceExtension->Rows; 296 columns = DeviceExtension->Columns; 297 298 _disable(); 299 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI); 300 offset = READ_PORT_UCHAR (CRTC_DATA)<<8; 301 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO); 302 offset += READ_PORT_UCHAR (CRTC_DATA); 303 _enable(); 304 305 cursory = offset / columns; 306 cursorx = offset % columns; 307 if( processed == 0 ) 308 { 309 /* raw output mode */ 310 memcpy( &vidmem[(cursorx * 2) + (cursory * columns * 2)], pch, stk->Parameters.Write.Length ); 311 offset += (stk->Parameters.Write.Length / 2); 312 } 313 else { 314 for (i = 0; i < stk->Parameters.Write.Length; i++, pch++) 315 { 316 switch (*pch) 317 { 318 case '\b': 319 if (cursorx > 0) 320 { 321 cursorx--; 322 } 323 else if (cursory > 0) 324 { 325 cursorx = columns - 1; 326 cursory--; 327 } 328 vidmem[(cursorx * 2) + (cursory * columns * 2)] = ' '; 329 vidmem[(cursorx * 2) + (cursory * columns * 2) + 1] = (char) DeviceExtension->CharAttribute; 330 break; 331 332 case '\n': 333 cursory++; 334 cursorx = 0; 335 break; 336 337 case '\r': 338 cursorx = 0; 339 break; 340 341 case '\t': 342 offset = TAB_WIDTH - (cursorx % TAB_WIDTH); 343 for (j = 0; j < offset; j++) 344 { 345 vidmem[(cursorx * 2) + (cursory * columns * 2)] = ' '; 346 cursorx++; 347 348 if (cursorx >= columns) 349 { 350 cursory++; 351 cursorx = 0; 352 } 353 } 354 break; 355 356 default: 357 vidmem[(cursorx * 2) + (cursory * columns * 2)] = *pch; 358 vidmem[(cursorx * 2) + (cursory * columns * 2) + 1] = (char) DeviceExtension->CharAttribute; 359 cursorx++; 360 if (cursorx >= columns) 361 { 362 cursory++; 363 cursorx = 0; 364 } 365 break; 366 } 367 if (cursory >= rows) 368 { 369 unsigned short *LinePtr; 370 371 memcpy (vidmem, 372 &vidmem[columns * 2], 373 columns * (rows - 1) * 2); 374 375 LinePtr = (unsigned short *) &vidmem[columns * (rows - 1) * 2]; 376 377 for (j = 0; j < columns; j++) 378 { 379 LinePtr[j] = DeviceExtension->CharAttribute << 8; 380 } 381 cursory = rows - 1; 382 for (j = 0; j < columns; j++) 383 { 384 vidmem[(j * 2) + (cursory * columns * 2)] = ' '; 385 vidmem[(j * 2) + (cursory * columns * 2) + 1] = (char)DeviceExtension->CharAttribute; 386 } 387 } 388 } 389 390 /* Set the cursor position */ 391 offset = (cursory * columns) + cursorx; 392 } 393 _disable(); 394 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO); 395 WRITE_PORT_UCHAR (CRTC_DATA, offset); 396 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI); 397 offset >>= 8; 398 WRITE_PORT_UCHAR (CRTC_DATA, offset); 399 _enable(); 400 401 Status = STATUS_SUCCESS; 402 403 Irp->IoStatus.Status = Status; 404 IoCompleteRequest (Irp, IO_NO_INCREMENT); 405 406 return (Status); 407 } 408 409 static DRIVER_DISPATCH ScrIoControl; 410 static NTSTATUS NTAPI 411 ScrIoControl(PDEVICE_OBJECT DeviceObject, 412 PIRP Irp) 413 { 414 PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation (Irp); 415 PDEVICE_EXTENSION DeviceExtension; 416 NTSTATUS Status; 417 418 DeviceExtension = DeviceObject->DeviceExtension; 419 switch (stk->Parameters.DeviceIoControl.IoControlCode) 420 { 421 case IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO: 422 { 423 PCONSOLE_SCREEN_BUFFER_INFO pcsbi = (PCONSOLE_SCREEN_BUFFER_INFO)Irp->AssociatedIrp.SystemBuffer; 424 int rows = DeviceExtension->Rows; 425 int columns = DeviceExtension->Columns; 426 unsigned int offset; 427 428 if (!InbvCheckDisplayOwnership()) 429 { 430 /* read cursor position from crtc */ 431 _disable(); 432 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO); 433 offset = READ_PORT_UCHAR (CRTC_DATA); 434 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI); 435 offset += (READ_PORT_UCHAR (CRTC_DATA) << 8); 436 _enable(); 437 } 438 else 439 { 440 offset = 0; 441 } 442 443 pcsbi->dwSize.X = columns; 444 pcsbi->dwSize.Y = rows; 445 446 pcsbi->dwCursorPosition.X = (SHORT)(offset % columns); 447 pcsbi->dwCursorPosition.Y = (SHORT)(offset / columns); 448 449 pcsbi->wAttributes = DeviceExtension->CharAttribute; 450 451 pcsbi->srWindow.Left = 0; 452 pcsbi->srWindow.Right = columns - 1; 453 pcsbi->srWindow.Top = 0; 454 pcsbi->srWindow.Bottom = rows - 1; 455 456 pcsbi->dwMaximumWindowSize.X = columns; 457 pcsbi->dwMaximumWindowSize.Y = rows; 458 459 Irp->IoStatus.Information = sizeof (CONSOLE_SCREEN_BUFFER_INFO); 460 Status = STATUS_SUCCESS; 461 } 462 break; 463 464 case IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO: 465 { 466 PCONSOLE_SCREEN_BUFFER_INFO pcsbi = (PCONSOLE_SCREEN_BUFFER_INFO)Irp->AssociatedIrp.SystemBuffer; 467 unsigned int offset; 468 469 DeviceExtension->CharAttribute = pcsbi->wAttributes; 470 offset = (pcsbi->dwCursorPosition.Y * DeviceExtension->Columns) + 471 pcsbi->dwCursorPosition.X; 472 473 if (!InbvCheckDisplayOwnership()) 474 { 475 _disable(); 476 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO); 477 WRITE_PORT_UCHAR (CRTC_DATA, offset); 478 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI); 479 WRITE_PORT_UCHAR (CRTC_DATA, offset>>8); 480 _enable(); 481 } 482 483 Irp->IoStatus.Information = 0; 484 Status = STATUS_SUCCESS; 485 } 486 break; 487 488 case IOCTL_CONSOLE_GET_CURSOR_INFO: 489 { 490 PCONSOLE_CURSOR_INFO pcci = (PCONSOLE_CURSOR_INFO)Irp->AssociatedIrp.SystemBuffer; 491 492 pcci->dwSize = DeviceExtension->CursorSize; 493 pcci->bVisible = DeviceExtension->CursorVisible; 494 495 Irp->IoStatus.Information = sizeof (CONSOLE_CURSOR_INFO); 496 Status = STATUS_SUCCESS; 497 } 498 break; 499 500 case IOCTL_CONSOLE_SET_CURSOR_INFO: 501 { 502 PCONSOLE_CURSOR_INFO pcci = (PCONSOLE_CURSOR_INFO)Irp->AssociatedIrp.SystemBuffer; 503 UCHAR data, value; 504 ULONG size, height; 505 506 DeviceExtension->CursorSize = pcci->dwSize; 507 DeviceExtension->CursorVisible = pcci->bVisible; 508 509 if (!InbvCheckDisplayOwnership()) 510 { 511 height = DeviceExtension->ScanLines; 512 data = (pcci->bVisible) ? 0x00 : 0x20; 513 514 size = (pcci->dwSize * height) / 100; 515 if (size < 1) 516 { 517 size = 1; 518 } 519 520 data |= (UCHAR)(height - size); 521 522 _disable(); 523 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORSTART); 524 WRITE_PORT_UCHAR (CRTC_DATA, data); 525 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSOREND); 526 value = READ_PORT_UCHAR (CRTC_DATA) & 0xE0; 527 WRITE_PORT_UCHAR (CRTC_DATA, value | (height - 1)); 528 529 _enable(); 530 } 531 532 Irp->IoStatus.Information = 0; 533 Status = STATUS_SUCCESS; 534 } 535 break; 536 537 case IOCTL_CONSOLE_GET_MODE: 538 { 539 PCONSOLE_MODE pcm = (PCONSOLE_MODE)Irp->AssociatedIrp.SystemBuffer; 540 541 pcm->dwMode = DeviceExtension->Mode; 542 543 Irp->IoStatus.Information = sizeof(CONSOLE_MODE); 544 Status = STATUS_SUCCESS; 545 } 546 break; 547 548 case IOCTL_CONSOLE_SET_MODE: 549 { 550 PCONSOLE_MODE pcm = (PCONSOLE_MODE)Irp->AssociatedIrp.SystemBuffer; 551 552 DeviceExtension->Mode = pcm->dwMode; 553 554 Irp->IoStatus.Information = 0; 555 Status = STATUS_SUCCESS; 556 } 557 break; 558 559 case IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE: 560 { 561 POUTPUT_ATTRIBUTE Buf = (POUTPUT_ATTRIBUTE)Irp->AssociatedIrp.SystemBuffer; 562 PUCHAR vidmem; 563 int offset; 564 ULONG dwCount; 565 566 if (!InbvCheckDisplayOwnership()) 567 { 568 vidmem = DeviceExtension->VideoMemory; 569 offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) + 570 (Buf->dwCoord.X * 2) + 1; 571 572 for (dwCount = 0; dwCount < Buf->nLength; dwCount++) 573 { 574 vidmem[offset + (dwCount * 2)] = (char) Buf->wAttribute; 575 } 576 } 577 578 Buf->dwTransfered = Buf->nLength; 579 580 Irp->IoStatus.Information = 0; 581 Status = STATUS_SUCCESS; 582 } 583 break; 584 585 case IOCTL_CONSOLE_READ_OUTPUT_ATTRIBUTE: 586 { 587 POUTPUT_ATTRIBUTE Buf = (POUTPUT_ATTRIBUTE)Irp->AssociatedIrp.SystemBuffer; 588 PUSHORT pAttr = (PUSHORT)MmGetSystemAddressForMdl(Irp->MdlAddress); 589 PUCHAR vidmem; 590 int offset; 591 ULONG dwCount; 592 593 if (!InbvCheckDisplayOwnership()) 594 { 595 vidmem = DeviceExtension->VideoMemory; 596 offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) + 597 (Buf->dwCoord.X * 2) + 1; 598 599 for (dwCount = 0; dwCount < stk->Parameters.DeviceIoControl.OutputBufferLength; dwCount++, pAttr++) 600 { 601 *((char *) pAttr) = vidmem[offset + (dwCount * 2)]; 602 } 603 604 Buf->dwTransfered = dwCount; 605 } 606 else 607 { 608 Buf->dwTransfered = 0; 609 } 610 611 Irp->IoStatus.Information = sizeof(OUTPUT_ATTRIBUTE); 612 Status = STATUS_SUCCESS; 613 } 614 break; 615 616 case IOCTL_CONSOLE_WRITE_OUTPUT_ATTRIBUTE: 617 { 618 COORD *pCoord = (COORD *)MmGetSystemAddressForMdl(Irp->MdlAddress); 619 CHAR *pAttr = (CHAR *)(pCoord + 1); 620 PUCHAR vidmem; 621 int offset; 622 ULONG dwCount; 623 624 if (!InbvCheckDisplayOwnership()) 625 { 626 vidmem = DeviceExtension->VideoMemory; 627 offset = (pCoord->Y * DeviceExtension->Columns * 2) + 628 (pCoord->X * 2) + 1; 629 630 for (dwCount = 0; dwCount < (stk->Parameters.DeviceIoControl.OutputBufferLength - sizeof( COORD )); dwCount++, pAttr++) 631 { 632 vidmem[offset + (dwCount * 2)] = *pAttr; 633 } 634 } 635 636 Irp->IoStatus.Information = 0; 637 Status = STATUS_SUCCESS; 638 } 639 break; 640 641 case IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE: 642 DeviceExtension->CharAttribute = (USHORT)*(PUSHORT)Irp->AssociatedIrp.SystemBuffer; 643 Irp->IoStatus.Information = 0; 644 Status = STATUS_SUCCESS; 645 break; 646 647 case IOCTL_CONSOLE_FILL_OUTPUT_CHARACTER: 648 { 649 POUTPUT_CHARACTER Buf = (POUTPUT_CHARACTER)Irp->AssociatedIrp.SystemBuffer; 650 PUCHAR vidmem; 651 int offset; 652 ULONG dwCount; 653 654 if (!InbvCheckDisplayOwnership()) 655 { 656 vidmem = DeviceExtension->VideoMemory; 657 offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) + 658 (Buf->dwCoord.X * 2); 659 660 661 for (dwCount = 0; dwCount < Buf->nLength; dwCount++) 662 { 663 vidmem[offset + (dwCount * 2)] = (char) Buf->cCharacter; 664 } 665 } 666 667 Buf->dwTransfered = Buf->nLength; 668 669 Irp->IoStatus.Information = 0; 670 Status = STATUS_SUCCESS; 671 } 672 break; 673 674 case IOCTL_CONSOLE_READ_OUTPUT_CHARACTER: 675 { 676 POUTPUT_CHARACTER Buf = (POUTPUT_CHARACTER)Irp->AssociatedIrp.SystemBuffer; 677 LPSTR pChar = (LPSTR)MmGetSystemAddressForMdl(Irp->MdlAddress); 678 PUCHAR vidmem; 679 int offset; 680 ULONG dwCount; 681 682 if (!InbvCheckDisplayOwnership()) 683 { 684 vidmem = DeviceExtension->VideoMemory; 685 offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) + 686 (Buf->dwCoord.X * 2); 687 688 for (dwCount = 0; dwCount < stk->Parameters.DeviceIoControl.OutputBufferLength; dwCount++, pChar++) 689 { 690 *pChar = vidmem[offset + (dwCount * 2)]; 691 } 692 693 Buf->dwTransfered = dwCount; 694 } 695 else 696 { 697 Buf->dwTransfered = 0; 698 } 699 700 Irp->IoStatus.Information = sizeof(OUTPUT_ATTRIBUTE); 701 Status = STATUS_SUCCESS; 702 } 703 break; 704 705 case IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER: 706 { 707 COORD *pCoord; 708 LPSTR pChar; 709 PUCHAR vidmem; 710 int offset; 711 ULONG dwCount; 712 713 if (!InbvCheckDisplayOwnership()) 714 { 715 pCoord = (COORD *)MmGetSystemAddressForMdl(Irp->MdlAddress); 716 pChar = (CHAR *)(pCoord + 1); 717 vidmem = DeviceExtension->VideoMemory; 718 offset = (pCoord->Y * DeviceExtension->Columns * 2) + 719 (pCoord->X * 2); 720 721 for (dwCount = 0; dwCount < (stk->Parameters.DeviceIoControl.OutputBufferLength - sizeof( COORD )); dwCount++, pChar++) 722 { 723 vidmem[offset + (dwCount * 2)] = *pChar; 724 } 725 } 726 727 Irp->IoStatus.Information = 0; 728 Status = STATUS_SUCCESS; 729 } 730 break; 731 732 case IOCTL_CONSOLE_DRAW: 733 { 734 PCONSOLE_DRAW ConsoleDraw; 735 PUCHAR Src, Dest; 736 UINT32 SrcDelta, DestDelta, i, Offset; 737 738 if (!InbvCheckDisplayOwnership()) 739 { 740 ConsoleDraw = (PCONSOLE_DRAW) MmGetSystemAddressForMdl(Irp->MdlAddress); 741 Src = (PUCHAR) (ConsoleDraw + 1); 742 SrcDelta = ConsoleDraw->SizeX * 2; 743 Dest = DeviceExtension->VideoMemory + 744 (ConsoleDraw->Y * DeviceExtension->Columns + ConsoleDraw->X) * 2; 745 DestDelta = DeviceExtension->Columns * 2; 746 747 for (i = 0; i < ConsoleDraw->SizeY; i++) 748 { 749 RtlCopyMemory(Dest, Src, SrcDelta); 750 Src += SrcDelta; 751 Dest += DestDelta; 752 } 753 754 Offset = (ConsoleDraw->CursorY * DeviceExtension->Columns) + 755 ConsoleDraw->CursorX; 756 757 _disable(); 758 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO); 759 WRITE_PORT_UCHAR (CRTC_DATA, Offset); 760 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI); 761 WRITE_PORT_UCHAR (CRTC_DATA, Offset >> 8); 762 _enable(); 763 } 764 765 Irp->IoStatus.Information = 0; 766 Status = STATUS_SUCCESS; 767 } 768 break; 769 770 case IOCTL_CONSOLE_LOADFONT: 771 { 772 UINT32 CodePage = (UINT32)*(PULONG)Irp->AssociatedIrp.SystemBuffer; 773 774 if (!InbvCheckDisplayOwnership()) 775 { 776 // Upload a font for the codepage if needed 777 ScrLoadFontTable(CodePage); 778 } 779 780 Irp->IoStatus.Information = 0; 781 Status = STATUS_SUCCESS; 782 } 783 break; 784 785 default: 786 Status = STATUS_NOT_IMPLEMENTED; 787 } 788 789 Irp->IoStatus.Status = Status; 790 IoCompleteRequest (Irp, IO_NO_INCREMENT); 791 792 return Status; 793 } 794 795 static DRIVER_DISPATCH ScrDispatch; 796 static NTSTATUS NTAPI 797 ScrDispatch(PDEVICE_OBJECT DeviceObject, 798 PIRP Irp) 799 { 800 PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp); 801 NTSTATUS Status; 802 803 switch (stk->MajorFunction) 804 { 805 case IRP_MJ_CLOSE: 806 Status = STATUS_SUCCESS; 807 break; 808 809 default: 810 Status = STATUS_NOT_IMPLEMENTED; 811 break; 812 } 813 814 815 Irp->IoStatus.Status = Status; 816 IoCompleteRequest (Irp, IO_NO_INCREMENT); 817 818 return (Status); 819 } 820 821 822 /* 823 * Module entry point 824 */ 825 NTSTATUS NTAPI 826 DriverEntry (PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) 827 { 828 PDEVICE_OBJECT DeviceObject; 829 NTSTATUS Status; 830 UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\BlueScreen"); 831 UNICODE_STRING SymlinkName = RTL_CONSTANT_STRING(L"\\??\\BlueScreen"); 832 833 DPRINT ("Screen Driver 0.0.6\n"); 834 835 DriverObject->MajorFunction[IRP_MJ_CREATE] = ScrCreate; 836 DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScrDispatch; 837 DriverObject->MajorFunction[IRP_MJ_READ] = ScrDispatch; 838 DriverObject->MajorFunction[IRP_MJ_WRITE] = ScrWrite; 839 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL ] = ScrIoControl; 840 841 Status = IoCreateDevice (DriverObject, 842 sizeof(DEVICE_EXTENSION), 843 &DeviceName, 844 FILE_DEVICE_SCREEN, 845 FILE_DEVICE_SECURE_OPEN, 846 TRUE, 847 &DeviceObject); 848 849 if (!NT_SUCCESS(Status)) 850 { 851 return Status; 852 } 853 854 Status = IoCreateSymbolicLink (&SymlinkName, &DeviceName); 855 if (NT_SUCCESS(Status)) 856 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; 857 else 858 IoDeleteDevice (DeviceObject); 859 return Status; 860 } 861 862 /* EOF */ 863