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