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