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