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