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 // FIXME: Does the buffer only contains chars? or chars + attributes? 311 // FIXME2: Fix buffer overflow. 312 memcpy( &vidmem[(cursorx * 2) + (cursory * columns * 2)], pch, stk->Parameters.Write.Length ); 313 offset += (stk->Parameters.Write.Length / 2); 314 } 315 else { 316 for (i = 0; i < stk->Parameters.Write.Length; i++, pch++) 317 { 318 switch (*pch) 319 { 320 case '\b': 321 if (cursorx > 0) 322 { 323 cursorx--; 324 } 325 else if (cursory > 0) 326 { 327 cursorx = columns - 1; 328 cursory--; 329 } 330 vidmem[(cursorx * 2) + (cursory * columns * 2)] = ' '; 331 vidmem[(cursorx * 2) + (cursory * columns * 2) + 1] = (char) DeviceExtension->CharAttribute; 332 break; 333 334 case '\n': 335 cursory++; 336 cursorx = 0; 337 break; 338 339 case '\r': 340 cursorx = 0; 341 break; 342 343 case '\t': 344 offset = TAB_WIDTH - (cursorx % TAB_WIDTH); 345 for (j = 0; j < offset; j++) 346 { 347 vidmem[(cursorx * 2) + (cursory * columns * 2)] = ' '; 348 cursorx++; 349 350 if (cursorx >= columns) 351 { 352 cursory++; 353 cursorx = 0; 354 } 355 } 356 break; 357 358 default: 359 vidmem[(cursorx * 2) + (cursory * columns * 2)] = *pch; 360 vidmem[(cursorx * 2) + (cursory * columns * 2) + 1] = (char) DeviceExtension->CharAttribute; 361 cursorx++; 362 if (cursorx >= columns) 363 { 364 cursory++; 365 cursorx = 0; 366 } 367 break; 368 } 369 370 /* Scroll up the contents of the screen if we are at the end */ 371 if (cursory >= rows) 372 { 373 unsigned short *LinePtr; 374 375 memcpy (vidmem, 376 &vidmem[columns * 2], 377 columns * (rows - 1) * 2); 378 379 LinePtr = (unsigned short *) &vidmem[columns * (rows - 1) * 2]; 380 381 for (j = 0; j < columns; j++) 382 { 383 LinePtr[j] = DeviceExtension->CharAttribute << 8; 384 } 385 cursory = rows - 1; 386 for (j = 0; j < columns; j++) 387 { 388 vidmem[(j * 2) + (cursory * columns * 2)] = ' '; 389 vidmem[(j * 2) + (cursory * columns * 2) + 1] = (char)DeviceExtension->CharAttribute; 390 } 391 } 392 } 393 394 /* Set the cursor position */ 395 offset = (cursory * columns) + cursorx; 396 } 397 _disable(); 398 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO); 399 WRITE_PORT_UCHAR (CRTC_DATA, offset); 400 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI); 401 offset >>= 8; 402 WRITE_PORT_UCHAR (CRTC_DATA, offset); 403 _enable(); 404 405 Status = STATUS_SUCCESS; 406 407 Irp->IoStatus.Status = Status; 408 IoCompleteRequest (Irp, IO_NO_INCREMENT); 409 410 return Status; 411 } 412 413 static DRIVER_DISPATCH ScrIoControl; 414 static NTSTATUS NTAPI 415 ScrIoControl(PDEVICE_OBJECT DeviceObject, 416 PIRP Irp) 417 { 418 PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation (Irp); 419 PDEVICE_EXTENSION DeviceExtension; 420 NTSTATUS Status; 421 422 DeviceExtension = DeviceObject->DeviceExtension; 423 switch (stk->Parameters.DeviceIoControl.IoControlCode) 424 { 425 case IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO: 426 { 427 PCONSOLE_SCREEN_BUFFER_INFO pcsbi = (PCONSOLE_SCREEN_BUFFER_INFO)Irp->AssociatedIrp.SystemBuffer; 428 int rows = DeviceExtension->Rows; 429 int columns = DeviceExtension->Columns; 430 unsigned int offset; 431 432 if (!InbvCheckDisplayOwnership()) 433 { 434 /* read cursor position from crtc */ 435 _disable(); 436 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO); 437 offset = READ_PORT_UCHAR (CRTC_DATA); 438 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI); 439 offset += (READ_PORT_UCHAR (CRTC_DATA) << 8); 440 _enable(); 441 } 442 else 443 { 444 offset = 0; 445 } 446 447 pcsbi->dwSize.X = columns; 448 pcsbi->dwSize.Y = rows; 449 450 pcsbi->dwCursorPosition.X = (SHORT)(offset % columns); 451 pcsbi->dwCursorPosition.Y = (SHORT)(offset / columns); 452 453 pcsbi->wAttributes = DeviceExtension->CharAttribute; 454 455 pcsbi->srWindow.Left = 0; 456 pcsbi->srWindow.Right = columns - 1; 457 pcsbi->srWindow.Top = 0; 458 pcsbi->srWindow.Bottom = rows - 1; 459 460 pcsbi->dwMaximumWindowSize.X = columns; 461 pcsbi->dwMaximumWindowSize.Y = rows; 462 463 Irp->IoStatus.Information = sizeof (CONSOLE_SCREEN_BUFFER_INFO); 464 Status = STATUS_SUCCESS; 465 } 466 break; 467 468 case IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO: 469 { 470 PCONSOLE_SCREEN_BUFFER_INFO pcsbi = (PCONSOLE_SCREEN_BUFFER_INFO)Irp->AssociatedIrp.SystemBuffer; 471 unsigned int offset; 472 473 if ( pcsbi->dwCursorPosition.X < 0 || pcsbi->dwCursorPosition.X >= DeviceExtension->Columns || 474 pcsbi->dwCursorPosition.Y < 0 || pcsbi->dwCursorPosition.Y >= DeviceExtension->Rows ) 475 { 476 Irp->IoStatus.Information = 0; 477 Status = STATUS_INVALID_PARAMETER; 478 break; 479 } 480 481 DeviceExtension->CharAttribute = pcsbi->wAttributes; 482 offset = (pcsbi->dwCursorPosition.Y * DeviceExtension->Columns) + 483 pcsbi->dwCursorPosition.X; 484 485 if (!InbvCheckDisplayOwnership()) 486 { 487 _disable(); 488 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO); 489 WRITE_PORT_UCHAR (CRTC_DATA, offset); 490 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI); 491 WRITE_PORT_UCHAR (CRTC_DATA, offset>>8); 492 _enable(); 493 } 494 495 Irp->IoStatus.Information = 0; 496 Status = STATUS_SUCCESS; 497 } 498 break; 499 500 case IOCTL_CONSOLE_GET_CURSOR_INFO: 501 { 502 PCONSOLE_CURSOR_INFO pcci = (PCONSOLE_CURSOR_INFO)Irp->AssociatedIrp.SystemBuffer; 503 504 pcci->dwSize = DeviceExtension->CursorSize; 505 pcci->bVisible = DeviceExtension->CursorVisible; 506 507 Irp->IoStatus.Information = sizeof (CONSOLE_CURSOR_INFO); 508 Status = STATUS_SUCCESS; 509 } 510 break; 511 512 case IOCTL_CONSOLE_SET_CURSOR_INFO: 513 { 514 PCONSOLE_CURSOR_INFO pcci = (PCONSOLE_CURSOR_INFO)Irp->AssociatedIrp.SystemBuffer; 515 UCHAR data, value; 516 ULONG size, height; 517 518 DeviceExtension->CursorSize = pcci->dwSize; 519 DeviceExtension->CursorVisible = pcci->bVisible; 520 521 if (!InbvCheckDisplayOwnership()) 522 { 523 height = DeviceExtension->ScanLines; 524 data = (pcci->bVisible) ? 0x00 : 0x20; 525 526 size = (pcci->dwSize * height) / 100; 527 if (size < 1) 528 { 529 size = 1; 530 } 531 532 data |= (UCHAR)(height - size); 533 534 _disable(); 535 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORSTART); 536 WRITE_PORT_UCHAR (CRTC_DATA, data); 537 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSOREND); 538 value = READ_PORT_UCHAR (CRTC_DATA) & 0xE0; 539 WRITE_PORT_UCHAR (CRTC_DATA, value | (height - 1)); 540 541 _enable(); 542 } 543 544 Irp->IoStatus.Information = 0; 545 Status = STATUS_SUCCESS; 546 } 547 break; 548 549 case IOCTL_CONSOLE_GET_MODE: 550 { 551 PCONSOLE_MODE pcm = (PCONSOLE_MODE)Irp->AssociatedIrp.SystemBuffer; 552 553 pcm->dwMode = DeviceExtension->Mode; 554 555 Irp->IoStatus.Information = sizeof(CONSOLE_MODE); 556 Status = STATUS_SUCCESS; 557 } 558 break; 559 560 case IOCTL_CONSOLE_SET_MODE: 561 { 562 PCONSOLE_MODE pcm = (PCONSOLE_MODE)Irp->AssociatedIrp.SystemBuffer; 563 564 DeviceExtension->Mode = pcm->dwMode; 565 566 Irp->IoStatus.Information = 0; 567 Status = STATUS_SUCCESS; 568 } 569 break; 570 571 case IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE: 572 { 573 POUTPUT_ATTRIBUTE Buf = (POUTPUT_ATTRIBUTE)Irp->AssociatedIrp.SystemBuffer; 574 PUCHAR vidmem; 575 int offset; 576 ULONG dwCount; 577 ULONG nMaxLength = Buf->nLength; 578 579 if ( Buf->dwCoord.X < 0 || Buf->dwCoord.X >= DeviceExtension->Columns || 580 Buf->dwCoord.Y < 0 || Buf->dwCoord.Y >= DeviceExtension->Rows ) 581 { 582 Buf->dwTransfered = 0; 583 Irp->IoStatus.Information = 0; 584 Status = STATUS_SUCCESS; 585 break; 586 } 587 588 if (!InbvCheckDisplayOwnership()) 589 { 590 vidmem = DeviceExtension->VideoMemory; 591 offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) + 592 (Buf->dwCoord.X * 2) + 1; 593 594 nMaxLength = min(nMaxLength, 595 (DeviceExtension->Rows - Buf->dwCoord.Y) 596 * DeviceExtension->Columns - Buf->dwCoord.X); 597 598 for (dwCount = 0; dwCount < nMaxLength; dwCount++) 599 { 600 vidmem[offset + (dwCount * 2)] = (char) Buf->wAttribute; 601 } 602 } 603 604 Buf->dwTransfered = nMaxLength; 605 606 Irp->IoStatus.Information = 0; 607 Status = STATUS_SUCCESS; 608 } 609 break; 610 611 case IOCTL_CONSOLE_READ_OUTPUT_ATTRIBUTE: 612 { 613 POUTPUT_ATTRIBUTE Buf = (POUTPUT_ATTRIBUTE)Irp->AssociatedIrp.SystemBuffer; 614 PUSHORT pAttr = (PUSHORT)MmGetSystemAddressForMdl(Irp->MdlAddress); 615 PUCHAR vidmem; 616 int offset; 617 ULONG dwCount; 618 ULONG nMaxLength; 619 620 if ( Buf->dwCoord.X < 0 || Buf->dwCoord.X >= DeviceExtension->Columns || 621 Buf->dwCoord.Y < 0 || Buf->dwCoord.Y >= DeviceExtension->Rows ) 622 { 623 Buf->dwTransfered = 0; 624 Irp->IoStatus.Information = 0; 625 Status = STATUS_SUCCESS; 626 break; 627 } 628 629 if (!InbvCheckDisplayOwnership()) 630 { 631 vidmem = DeviceExtension->VideoMemory; 632 offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) + 633 (Buf->dwCoord.X * 2) + 1; 634 635 nMaxLength = min(stk->Parameters.DeviceIoControl.OutputBufferLength, 636 (DeviceExtension->Rows - Buf->dwCoord.Y) 637 * DeviceExtension->Columns - Buf->dwCoord.X); 638 639 for (dwCount = 0; dwCount < nMaxLength; dwCount++, pAttr++) 640 { 641 *((char *)pAttr) = vidmem[offset + (dwCount * 2)]; 642 } 643 644 Buf->dwTransfered = dwCount; 645 } 646 else 647 { 648 Buf->dwTransfered = 0; 649 } 650 651 Irp->IoStatus.Information = sizeof(OUTPUT_ATTRIBUTE); 652 Status = STATUS_SUCCESS; 653 } 654 break; 655 656 case IOCTL_CONSOLE_WRITE_OUTPUT_ATTRIBUTE: 657 { 658 COORD *pCoord = (COORD *)MmGetSystemAddressForMdl(Irp->MdlAddress); 659 CHAR *pAttr = (CHAR *)(pCoord + 1); 660 PUCHAR vidmem; 661 int offset; 662 ULONG dwCount; 663 ULONG nMaxLength; 664 665 if ( pCoord->X < 0 || pCoord->X >= DeviceExtension->Columns || 666 pCoord->Y < 0 || pCoord->Y >= DeviceExtension->Rows ) 667 { 668 Irp->IoStatus.Information = 0; 669 Status = STATUS_SUCCESS; 670 break; 671 } 672 673 if (!InbvCheckDisplayOwnership()) 674 { 675 vidmem = DeviceExtension->VideoMemory; 676 offset = (pCoord->Y * DeviceExtension->Columns * 2) + 677 (pCoord->X * 2) + 1; 678 679 nMaxLength = min(stk->Parameters.DeviceIoControl.OutputBufferLength - sizeof(COORD), 680 (DeviceExtension->Rows - pCoord->Y) 681 * DeviceExtension->Columns - pCoord->X); 682 683 for (dwCount = 0; dwCount < nMaxLength; dwCount++, pAttr++) 684 { 685 vidmem[offset + (dwCount * 2)] = *pAttr; 686 } 687 } 688 689 Irp->IoStatus.Information = 0; 690 Status = STATUS_SUCCESS; 691 } 692 break; 693 694 case IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE: 695 DeviceExtension->CharAttribute = (USHORT)*(PUSHORT)Irp->AssociatedIrp.SystemBuffer; 696 Irp->IoStatus.Information = 0; 697 Status = STATUS_SUCCESS; 698 break; 699 700 case IOCTL_CONSOLE_FILL_OUTPUT_CHARACTER: 701 { 702 POUTPUT_CHARACTER Buf = (POUTPUT_CHARACTER)Irp->AssociatedIrp.SystemBuffer; 703 PUCHAR vidmem; 704 int offset; 705 ULONG dwCount; 706 ULONG nMaxLength = Buf->nLength; 707 708 if ( Buf->dwCoord.X < 0 || Buf->dwCoord.X >= DeviceExtension->Columns || 709 Buf->dwCoord.Y < 0 || Buf->dwCoord.Y >= DeviceExtension->Rows ) 710 { 711 Buf->dwTransfered = 0; 712 Irp->IoStatus.Information = 0; 713 Status = STATUS_SUCCESS; 714 break; 715 } 716 717 if (!InbvCheckDisplayOwnership()) 718 { 719 vidmem = DeviceExtension->VideoMemory; 720 offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) + 721 (Buf->dwCoord.X * 2); 722 723 nMaxLength = min(nMaxLength, 724 (DeviceExtension->Rows - Buf->dwCoord.Y) 725 * DeviceExtension->Columns - Buf->dwCoord.X); 726 727 for (dwCount = 0; dwCount < nMaxLength; dwCount++) 728 { 729 vidmem[offset + (dwCount * 2)] = (char) Buf->cCharacter; 730 } 731 } 732 733 Buf->dwTransfered = nMaxLength; 734 735 Irp->IoStatus.Information = 0; 736 Status = STATUS_SUCCESS; 737 } 738 break; 739 740 case IOCTL_CONSOLE_READ_OUTPUT_CHARACTER: 741 { 742 POUTPUT_CHARACTER Buf = (POUTPUT_CHARACTER)Irp->AssociatedIrp.SystemBuffer; 743 LPSTR pChar = (LPSTR)MmGetSystemAddressForMdl(Irp->MdlAddress); 744 PUCHAR vidmem; 745 int offset; 746 ULONG dwCount; 747 ULONG nMaxLength; 748 749 if ( Buf->dwCoord.X < 0 || Buf->dwCoord.X >= DeviceExtension->Columns || 750 Buf->dwCoord.Y < 0 || Buf->dwCoord.Y >= DeviceExtension->Rows ) 751 { 752 Buf->dwTransfered = 0; 753 Irp->IoStatus.Information = 0; 754 Status = STATUS_SUCCESS; 755 break; 756 } 757 758 if (!InbvCheckDisplayOwnership()) 759 { 760 vidmem = DeviceExtension->VideoMemory; 761 offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) + 762 (Buf->dwCoord.X * 2); 763 764 nMaxLength = min(stk->Parameters.DeviceIoControl.OutputBufferLength, 765 (DeviceExtension->Rows - Buf->dwCoord.Y) 766 * DeviceExtension->Columns - Buf->dwCoord.X); 767 768 for (dwCount = 0; dwCount < nMaxLength; dwCount++, pChar++) 769 { 770 *pChar = vidmem[offset + (dwCount * 2)]; 771 } 772 773 Buf->dwTransfered = dwCount; 774 } 775 else 776 { 777 Buf->dwTransfered = 0; 778 } 779 780 Irp->IoStatus.Information = sizeof(OUTPUT_ATTRIBUTE); 781 Status = STATUS_SUCCESS; 782 } 783 break; 784 785 case IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER: 786 { 787 COORD *pCoord = (COORD *)MmGetSystemAddressForMdl(Irp->MdlAddress); 788 LPSTR pChar = (CHAR *)(pCoord + 1); 789 PUCHAR vidmem; 790 int offset; 791 ULONG dwCount; 792 ULONG nMaxLength; 793 794 if ( pCoord->X < 0 || pCoord->X >= DeviceExtension->Columns || 795 pCoord->Y < 0 || pCoord->Y >= DeviceExtension->Rows ) 796 { 797 Irp->IoStatus.Information = 0; 798 Status = STATUS_SUCCESS; 799 break; 800 } 801 802 if (!InbvCheckDisplayOwnership()) 803 { 804 vidmem = DeviceExtension->VideoMemory; 805 offset = (pCoord->Y * DeviceExtension->Columns * 2) + 806 (pCoord->X * 2); 807 808 nMaxLength = min(stk->Parameters.DeviceIoControl.OutputBufferLength - sizeof(COORD), 809 (DeviceExtension->Rows - pCoord->Y) 810 * DeviceExtension->Columns - pCoord->X); 811 812 for (dwCount = 0; dwCount < nMaxLength; dwCount++, pChar++) 813 { 814 vidmem[offset + (dwCount * 2)] = *pChar; 815 } 816 } 817 818 Irp->IoStatus.Information = 0; 819 Status = STATUS_SUCCESS; 820 } 821 break; 822 823 case IOCTL_CONSOLE_DRAW: 824 { 825 PCONSOLE_DRAW ConsoleDraw; 826 PUCHAR Src, Dest; 827 UINT32 SrcDelta, DestDelta, i, Offset; 828 829 if (!InbvCheckDisplayOwnership()) 830 { 831 ConsoleDraw = (PCONSOLE_DRAW) MmGetSystemAddressForMdl(Irp->MdlAddress); 832 Src = (PUCHAR) (ConsoleDraw + 1); 833 SrcDelta = ConsoleDraw->SizeX * 2; 834 Dest = DeviceExtension->VideoMemory + 835 (ConsoleDraw->Y * DeviceExtension->Columns + ConsoleDraw->X) * 2; 836 DestDelta = DeviceExtension->Columns * 2; 837 838 for (i = 0; i < ConsoleDraw->SizeY; i++) 839 { 840 RtlCopyMemory(Dest, Src, SrcDelta); 841 Src += SrcDelta; 842 Dest += DestDelta; 843 } 844 845 Offset = (ConsoleDraw->CursorY * DeviceExtension->Columns) + 846 ConsoleDraw->CursorX; 847 848 _disable(); 849 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO); 850 WRITE_PORT_UCHAR (CRTC_DATA, Offset); 851 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI); 852 WRITE_PORT_UCHAR (CRTC_DATA, Offset >> 8); 853 _enable(); 854 } 855 856 Irp->IoStatus.Information = 0; 857 Status = STATUS_SUCCESS; 858 } 859 break; 860 861 case IOCTL_CONSOLE_LOADFONT: 862 { 863 UINT32 CodePage = (UINT32)*(PULONG)Irp->AssociatedIrp.SystemBuffer; 864 865 if (!InbvCheckDisplayOwnership()) 866 { 867 // Upload a font for the codepage if needed 868 ScrLoadFontTable(CodePage); 869 } 870 871 Irp->IoStatus.Information = 0; 872 Status = STATUS_SUCCESS; 873 } 874 break; 875 876 default: 877 Status = STATUS_NOT_IMPLEMENTED; 878 } 879 880 Irp->IoStatus.Status = Status; 881 IoCompleteRequest (Irp, IO_NO_INCREMENT); 882 883 return Status; 884 } 885 886 static DRIVER_DISPATCH ScrDispatch; 887 static NTSTATUS NTAPI 888 ScrDispatch(PDEVICE_OBJECT DeviceObject, 889 PIRP Irp) 890 { 891 PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp); 892 NTSTATUS Status; 893 894 switch (stk->MajorFunction) 895 { 896 case IRP_MJ_CLOSE: 897 Status = STATUS_SUCCESS; 898 break; 899 900 default: 901 Status = STATUS_NOT_IMPLEMENTED; 902 break; 903 } 904 905 906 Irp->IoStatus.Status = Status; 907 IoCompleteRequest (Irp, IO_NO_INCREMENT); 908 909 return Status; 910 } 911 912 913 /* 914 * Module entry point 915 */ 916 NTSTATUS NTAPI 917 DriverEntry (PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) 918 { 919 PDEVICE_OBJECT DeviceObject; 920 NTSTATUS Status; 921 UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\BlueScreen"); 922 UNICODE_STRING SymlinkName = RTL_CONSTANT_STRING(L"\\??\\BlueScreen"); 923 924 DPRINT ("Screen Driver 0.0.6\n"); 925 926 DriverObject->MajorFunction[IRP_MJ_CREATE] = ScrCreate; 927 DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScrDispatch; 928 DriverObject->MajorFunction[IRP_MJ_READ] = ScrDispatch; 929 DriverObject->MajorFunction[IRP_MJ_WRITE] = ScrWrite; 930 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL ] = ScrIoControl; 931 932 Status = IoCreateDevice (DriverObject, 933 sizeof(DEVICE_EXTENSION), 934 &DeviceName, 935 FILE_DEVICE_SCREEN, 936 FILE_DEVICE_SECURE_OPEN, 937 TRUE, 938 &DeviceObject); 939 940 if (!NT_SUCCESS(Status)) 941 { 942 return Status; 943 } 944 945 Status = IoCreateSymbolicLink (&SymlinkName, &DeviceName); 946 if (NT_SUCCESS(Status)) 947 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; 948 else 949 IoDeleteDevice (DeviceObject); 950 return Status; 951 } 952 953 /* EOF */ 954