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