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