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