* Sync to trunk HEAD (r53318).
[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 ScrAcquireOwnership(DeviceExtension);
236
237 /* get pointer to video memory */
238 BaseAddress.QuadPart = VIDMEM_BASE;
239 DeviceExtension->VideoMemory =
240 (PUCHAR)MmMapIoSpace (BaseAddress, DeviceExtension->Rows * DeviceExtension->Columns * 2, MmNonCached);
241
242 DeviceExtension->CursorSize = 5; /* FIXME: value correct?? */
243 DeviceExtension->CursorVisible = TRUE;
244
245 /* more initialization */
246 DeviceExtension->CharAttribute = 0x17; /* light grey on blue */
247 DeviceExtension->Mode = ENABLE_PROCESSED_OUTPUT |
248 ENABLE_WRAP_AT_EOL_OUTPUT;
249
250 Status = STATUS_SUCCESS;
251
252 Irp->IoStatus.Status = Status;
253 IoCompleteRequest (Irp, IO_NO_INCREMENT);
254
255 return (Status);
256 }
257
258 static DRIVER_DISPATCH ScrWrite;
259 static NTSTATUS NTAPI
260 ScrWrite(PDEVICE_OBJECT DeviceObject,
261 PIRP Irp)
262 {
263 PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation (Irp);
264 PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
265 NTSTATUS Status;
266 char *pch = Irp->UserBuffer;
267 PUCHAR vidmem;
268 unsigned int i;
269 int j, offset;
270 int cursorx, cursory;
271 int rows, columns;
272 int processed = DeviceExtension->Mode & ENABLE_PROCESSED_OUTPUT;
273
274 if (0 && InbvCheckDisplayOwnership())
275 {
276 /* Display is in graphics mode, we're not allowed to touch it */
277 Status = STATUS_SUCCESS;
278
279 Irp->IoStatus.Status = Status;
280 IoCompleteRequest (Irp, IO_NO_INCREMENT);
281
282 return Status;
283 }
284
285 vidmem = DeviceExtension->VideoMemory;
286 rows = DeviceExtension->Rows;
287 columns = DeviceExtension->Columns;
288
289 _disable();
290 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI);
291 offset = READ_PORT_UCHAR (CRTC_DATA)<<8;
292 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO);
293 offset += READ_PORT_UCHAR (CRTC_DATA);
294 _enable();
295
296 cursory = offset / columns;
297 cursorx = offset % columns;
298 if( processed == 0 )
299 {
300 /* raw output mode */
301 memcpy( &vidmem[(cursorx * 2) + (cursory * columns * 2)], pch, stk->Parameters.Write.Length );
302 offset += (stk->Parameters.Write.Length / 2);
303 }
304 else {
305 for (i = 0; i < stk->Parameters.Write.Length; i++, pch++)
306 {
307 switch (*pch)
308 {
309 case '\b':
310 if (cursorx > 0)
311 {
312 cursorx--;
313 }
314 else if (cursory > 0)
315 {
316 cursorx = columns - 1;
317 cursory--;
318 }
319 vidmem[(cursorx * 2) + (cursory * columns * 2)] = ' ';
320 vidmem[(cursorx * 2) + (cursory * columns * 2) + 1] = (char) DeviceExtension->CharAttribute;
321 break;
322
323 case '\n':
324 cursory++;
325 cursorx = 0;
326 break;
327
328 case '\r':
329 cursorx = 0;
330 break;
331
332 case '\t':
333 offset = TAB_WIDTH - (cursorx % TAB_WIDTH);
334 for (j = 0; j < offset; j++)
335 {
336 vidmem[(cursorx * 2) + (cursory * columns * 2)] = ' ';
337 cursorx++;
338
339 if (cursorx >= columns)
340 {
341 cursory++;
342 cursorx = 0;
343 }
344 }
345 break;
346
347 default:
348 vidmem[(cursorx * 2) + (cursory * columns * 2)] = *pch;
349 vidmem[(cursorx * 2) + (cursory * columns * 2) + 1] = (char) DeviceExtension->CharAttribute;
350 cursorx++;
351 if (cursorx >= columns)
352 {
353 cursory++;
354 cursorx = 0;
355 }
356 break;
357 }
358 if (cursory >= rows)
359 {
360 unsigned short *LinePtr;
361
362 memcpy (vidmem,
363 &vidmem[columns * 2],
364 columns * (rows - 1) * 2);
365
366 LinePtr = (unsigned short *) &vidmem[columns * (rows - 1) * 2];
367
368 for (j = 0; j < columns; j++)
369 {
370 LinePtr[j] = DeviceExtension->CharAttribute << 8;
371 }
372 cursory = rows - 1;
373 for (j = 0; j < columns; j++)
374 {
375 vidmem[(j * 2) + (cursory * columns * 2)] = ' ';
376 vidmem[(j * 2) + (cursory * columns * 2) + 1] = (char)DeviceExtension->CharAttribute;
377 }
378 }
379 }
380
381 /* Set the cursor position */
382 offset = (cursory * columns) + cursorx;
383 }
384 _disable();
385 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO);
386 WRITE_PORT_UCHAR (CRTC_DATA, offset);
387 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI);
388 offset >>= 8;
389 WRITE_PORT_UCHAR (CRTC_DATA, offset);
390 _enable();
391
392 Status = STATUS_SUCCESS;
393
394 Irp->IoStatus.Status = Status;
395 IoCompleteRequest (Irp, IO_NO_INCREMENT);
396
397 return (Status);
398 }
399
400 static DRIVER_DISPATCH ScrIoControl;
401 static NTSTATUS NTAPI
402 ScrIoControl(PDEVICE_OBJECT DeviceObject,
403 PIRP Irp)
404 {
405 PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation (Irp);
406 PDEVICE_EXTENSION DeviceExtension;
407 NTSTATUS Status;
408
409 DeviceExtension = DeviceObject->DeviceExtension;
410 switch (stk->Parameters.DeviceIoControl.IoControlCode)
411 {
412 case IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO:
413 {
414 PCONSOLE_SCREEN_BUFFER_INFO pcsbi = (PCONSOLE_SCREEN_BUFFER_INFO)Irp->AssociatedIrp.SystemBuffer;
415 int rows = DeviceExtension->Rows;
416 int columns = DeviceExtension->Columns;
417 unsigned int offset;
418
419 /* read cursor position from crtc */
420 _disable();
421 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO);
422 offset = READ_PORT_UCHAR (CRTC_DATA);
423 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI);
424 offset += (READ_PORT_UCHAR (CRTC_DATA) << 8);
425 _enable();
426
427 pcsbi->dwSize.X = columns;
428 pcsbi->dwSize.Y = rows;
429
430 pcsbi->dwCursorPosition.X = (SHORT)(offset % columns);
431 pcsbi->dwCursorPosition.Y = (SHORT)(offset / columns);
432
433 pcsbi->wAttributes = DeviceExtension->CharAttribute;
434
435 pcsbi->srWindow.Left = 0;
436 pcsbi->srWindow.Right = columns - 1;
437 pcsbi->srWindow.Top = 0;
438 pcsbi->srWindow.Bottom = rows - 1;
439
440 pcsbi->dwMaximumWindowSize.X = columns;
441 pcsbi->dwMaximumWindowSize.Y = rows;
442
443 Irp->IoStatus.Information = sizeof (CONSOLE_SCREEN_BUFFER_INFO);
444 Status = STATUS_SUCCESS;
445 }
446 break;
447
448 case IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO:
449 {
450 PCONSOLE_SCREEN_BUFFER_INFO pcsbi = (PCONSOLE_SCREEN_BUFFER_INFO)Irp->AssociatedIrp.SystemBuffer;
451 unsigned int offset;
452
453 DeviceExtension->CharAttribute = pcsbi->wAttributes;
454 offset = (pcsbi->dwCursorPosition.Y * DeviceExtension->Columns) +
455 pcsbi->dwCursorPosition.X;
456
457 _disable();
458 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO);
459 WRITE_PORT_UCHAR (CRTC_DATA, offset);
460 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI);
461 WRITE_PORT_UCHAR (CRTC_DATA, offset>>8);
462 _enable();
463
464 Irp->IoStatus.Information = 0;
465 Status = STATUS_SUCCESS;
466 }
467 break;
468
469 case IOCTL_CONSOLE_GET_CURSOR_INFO:
470 {
471 PCONSOLE_CURSOR_INFO pcci = (PCONSOLE_CURSOR_INFO)Irp->AssociatedIrp.SystemBuffer;
472
473 pcci->dwSize = DeviceExtension->CursorSize;
474 pcci->bVisible = DeviceExtension->CursorVisible;
475
476 Irp->IoStatus.Information = sizeof (CONSOLE_CURSOR_INFO);
477 Status = STATUS_SUCCESS;
478 }
479 break;
480
481 case IOCTL_CONSOLE_SET_CURSOR_INFO:
482 {
483 PCONSOLE_CURSOR_INFO pcci = (PCONSOLE_CURSOR_INFO)Irp->AssociatedIrp.SystemBuffer;
484 UCHAR data, value;
485 ULONG size, height;
486
487 DeviceExtension->CursorSize = pcci->dwSize;
488 DeviceExtension->CursorVisible = pcci->bVisible;
489 height = DeviceExtension->ScanLines;
490 data = (pcci->bVisible) ? 0x00 : 0x20;
491
492 size = (pcci->dwSize * height) / 100;
493 if (size < 1)
494 {
495 size = 1;
496 }
497
498 data |= (UCHAR)(height - size);
499
500 _disable();
501 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORSTART);
502 WRITE_PORT_UCHAR (CRTC_DATA, data);
503 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSOREND);
504 value = READ_PORT_UCHAR (CRTC_DATA) & 0xE0;
505 WRITE_PORT_UCHAR (CRTC_DATA, value | (height - 1));
506
507 _enable();
508
509 Irp->IoStatus.Information = 0;
510 Status = STATUS_SUCCESS;
511 }
512 break;
513
514 case IOCTL_CONSOLE_GET_MODE:
515 {
516 PCONSOLE_MODE pcm = (PCONSOLE_MODE)Irp->AssociatedIrp.SystemBuffer;
517
518 pcm->dwMode = DeviceExtension->Mode;
519
520 Irp->IoStatus.Information = sizeof(CONSOLE_MODE);
521 Status = STATUS_SUCCESS;
522 }
523 break;
524
525 case IOCTL_CONSOLE_SET_MODE:
526 {
527 PCONSOLE_MODE pcm = (PCONSOLE_MODE)Irp->AssociatedIrp.SystemBuffer;
528
529 DeviceExtension->Mode = pcm->dwMode;
530
531 Irp->IoStatus.Information = 0;
532 Status = STATUS_SUCCESS;
533 }
534 break;
535
536 case IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE:
537 {
538 POUTPUT_ATTRIBUTE Buf = (POUTPUT_ATTRIBUTE)Irp->AssociatedIrp.SystemBuffer;
539 PUCHAR vidmem;
540 int offset;
541 ULONG dwCount;
542
543 vidmem = DeviceExtension->VideoMemory;
544 offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) +
545 (Buf->dwCoord.X * 2) + 1;
546
547 for (dwCount = 0; dwCount < Buf->nLength; dwCount++)
548 {
549 vidmem[offset + (dwCount * 2)] = (char) Buf->wAttribute;
550 }
551
552 Buf->dwTransfered = Buf->nLength;
553
554 Irp->IoStatus.Information = 0;
555 Status = STATUS_SUCCESS;
556 }
557 break;
558
559 case IOCTL_CONSOLE_READ_OUTPUT_ATTRIBUTE:
560 {
561 POUTPUT_ATTRIBUTE Buf = (POUTPUT_ATTRIBUTE)Irp->AssociatedIrp.SystemBuffer;
562 PUSHORT pAttr = (PUSHORT)MmGetSystemAddressForMdl(Irp->MdlAddress);
563 PUCHAR vidmem;
564 int offset;
565 ULONG dwCount;
566
567 vidmem = DeviceExtension->VideoMemory;
568 offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) +
569 (Buf->dwCoord.X * 2) + 1;
570
571 for (dwCount = 0; dwCount < stk->Parameters.DeviceIoControl.OutputBufferLength; dwCount++, pAttr++)
572 {
573 *((char *) pAttr) = vidmem[offset + (dwCount * 2)];
574 }
575
576 Buf->dwTransfered = dwCount;
577
578 Irp->IoStatus.Information = sizeof(OUTPUT_ATTRIBUTE);
579 Status = STATUS_SUCCESS;
580 }
581 break;
582
583 case IOCTL_CONSOLE_WRITE_OUTPUT_ATTRIBUTE:
584 {
585 COORD *pCoord = (COORD *)MmGetSystemAddressForMdl(Irp->MdlAddress);
586 CHAR *pAttr = (CHAR *)(pCoord + 1);
587 PUCHAR vidmem;
588 int offset;
589 ULONG dwCount;
590
591 vidmem = DeviceExtension->VideoMemory;
592 offset = (pCoord->Y * DeviceExtension->Columns * 2) +
593 (pCoord->X * 2) + 1;
594
595 for (dwCount = 0; dwCount < (stk->Parameters.DeviceIoControl.OutputBufferLength - sizeof( COORD )); dwCount++, pAttr++)
596 {
597 vidmem[offset + (dwCount * 2)] = *pAttr;
598 }
599 Irp->IoStatus.Information = 0;
600 Status = STATUS_SUCCESS;
601 }
602 break;
603
604 case IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE:
605 DeviceExtension->CharAttribute = (USHORT)*(PUSHORT)Irp->AssociatedIrp.SystemBuffer;
606 Irp->IoStatus.Information = 0;
607 Status = STATUS_SUCCESS;
608 break;
609
610 case IOCTL_CONSOLE_FILL_OUTPUT_CHARACTER:
611 {
612 POUTPUT_CHARACTER Buf = (POUTPUT_CHARACTER)Irp->AssociatedIrp.SystemBuffer;
613 PUCHAR vidmem;
614 int offset;
615 ULONG dwCount;
616
617 vidmem = DeviceExtension->VideoMemory;
618 offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) +
619 (Buf->dwCoord.X * 2);
620
621
622 for (dwCount = 0; dwCount < Buf->nLength; dwCount++)
623 {
624 vidmem[offset + (dwCount * 2)] = (char) Buf->cCharacter;
625 }
626
627 Buf->dwTransfered = Buf->nLength;
628
629 Irp->IoStatus.Information = 0;
630 Status = STATUS_SUCCESS;
631 }
632 break;
633
634 case IOCTL_CONSOLE_READ_OUTPUT_CHARACTER:
635 {
636 POUTPUT_CHARACTER Buf = (POUTPUT_CHARACTER)Irp->AssociatedIrp.SystemBuffer;
637 LPSTR pChar = (LPSTR)MmGetSystemAddressForMdl(Irp->MdlAddress);
638 PUCHAR vidmem;
639 int offset;
640 ULONG dwCount;
641
642 vidmem = DeviceExtension->VideoMemory;
643 offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) +
644 (Buf->dwCoord.X * 2);
645
646 for (dwCount = 0; dwCount < stk->Parameters.DeviceIoControl.OutputBufferLength; dwCount++, pChar++)
647 {
648 *pChar = vidmem[offset + (dwCount * 2)];
649 }
650
651 Buf->dwTransfered = dwCount;
652
653 Irp->IoStatus.Information = sizeof(OUTPUT_ATTRIBUTE);
654 Status = STATUS_SUCCESS;
655 }
656 break;
657
658 case IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER:
659 {
660 COORD *pCoord;
661 LPSTR pChar;
662 PUCHAR vidmem;
663 int offset;
664 ULONG dwCount;
665
666 pCoord = (COORD *)MmGetSystemAddressForMdl(Irp->MdlAddress);
667 pChar = (CHAR *)(pCoord + 1);
668 vidmem = DeviceExtension->VideoMemory;
669 offset = (pCoord->Y * DeviceExtension->Columns * 2) +
670 (pCoord->X * 2);
671
672 for (dwCount = 0; dwCount < (stk->Parameters.DeviceIoControl.OutputBufferLength - sizeof( COORD )); dwCount++, pChar++)
673 {
674 vidmem[offset + (dwCount * 2)] = *pChar;
675 }
676
677 Irp->IoStatus.Information = 0;
678 Status = STATUS_SUCCESS;
679 }
680 break;
681
682 case IOCTL_CONSOLE_DRAW:
683 {
684 PCONSOLE_DRAW ConsoleDraw;
685 PUCHAR Src, Dest;
686 UINT32 SrcDelta, DestDelta, i, Offset;
687
688 ConsoleDraw = (PCONSOLE_DRAW) MmGetSystemAddressForMdl(Irp->MdlAddress);
689 Src = (PUCHAR) (ConsoleDraw + 1);
690 SrcDelta = ConsoleDraw->SizeX * 2;
691 Dest = DeviceExtension->VideoMemory +
692 (ConsoleDraw->Y * DeviceExtension->Columns + ConsoleDraw->X) * 2;
693 DestDelta = DeviceExtension->Columns * 2;
694
695 for (i = 0; i < ConsoleDraw->SizeY; i++)
696 {
697 RtlCopyMemory(Dest, Src, SrcDelta);
698 Src += SrcDelta;
699 Dest += DestDelta;
700 }
701
702 Offset = (ConsoleDraw->CursorY * DeviceExtension->Columns) +
703 ConsoleDraw->CursorX;
704
705 _disable();
706 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO);
707 WRITE_PORT_UCHAR (CRTC_DATA, Offset);
708 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI);
709 WRITE_PORT_UCHAR (CRTC_DATA, Offset >> 8);
710 _enable();
711
712 Irp->IoStatus.Information = 0;
713 Status = STATUS_SUCCESS;
714 }
715 break;
716
717 case IOCTL_CONSOLE_LOADFONT:
718 {
719 UINT32 CodePage = (UINT32)*(PULONG)Irp->AssociatedIrp.SystemBuffer;
720
721 // Upload a font for the codepage if needed
722 ScrLoadFontTable(CodePage);
723
724 Irp->IoStatus.Information = 0;
725 Status = STATUS_SUCCESS;
726 }
727 break;
728
729 default:
730 Status = STATUS_NOT_IMPLEMENTED;
731 }
732
733 Irp->IoStatus.Status = Status;
734 IoCompleteRequest (Irp, IO_NO_INCREMENT);
735
736 return Status;
737 }
738
739 static DRIVER_DISPATCH ScrDispatch;
740 static NTSTATUS NTAPI
741 ScrDispatch(PDEVICE_OBJECT DeviceObject,
742 PIRP Irp)
743 {
744 PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
745 NTSTATUS Status;
746
747 switch (stk->MajorFunction)
748 {
749 case IRP_MJ_CLOSE:
750 Status = STATUS_SUCCESS;
751 break;
752
753 default:
754 Status = STATUS_NOT_IMPLEMENTED;
755 break;
756 }
757
758
759 Irp->IoStatus.Status = Status;
760 IoCompleteRequest (Irp, IO_NO_INCREMENT);
761
762 return (Status);
763 }
764
765
766 /*
767 * Module entry point
768 */
769 NTSTATUS NTAPI
770 DriverEntry (PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
771 {
772 PDEVICE_OBJECT DeviceObject;
773 NTSTATUS Status;
774 UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\BlueScreen");
775 UNICODE_STRING SymlinkName = RTL_CONSTANT_STRING(L"\\??\\BlueScreen");
776
777 DPRINT ("Screen Driver 0.0.6\n");
778
779 DriverObject->MajorFunction[IRP_MJ_CREATE] = ScrCreate;
780 DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScrDispatch;
781 DriverObject->MajorFunction[IRP_MJ_READ] = ScrDispatch;
782 DriverObject->MajorFunction[IRP_MJ_WRITE] = ScrWrite;
783 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL ] = ScrIoControl;
784
785 Status = IoCreateDevice (DriverObject,
786 sizeof(DEVICE_EXTENSION),
787 &DeviceName,
788 FILE_DEVICE_SCREEN,
789 FILE_DEVICE_SECURE_OPEN,
790 TRUE,
791 &DeviceObject);
792
793 if (!NT_SUCCESS(Status))
794 {
795 return Status;
796 }
797
798 Status = IoCreateSymbolicLink (&SymlinkName, &DeviceName);
799 if (NT_SUCCESS(Status))
800 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
801 else
802 IoDeleteDevice (DeviceObject);
803 return Status;
804 }
805
806 /* EOF */