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