3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: services/dd/blue/blue.c
6 * PURPOSE: Console (blue screen) device driver
7 * PROGRAMMER: Eric Kohl (ekohl@abo.rhein-zeitung.de)
12 /* INCLUDES ******************************************************************/
14 #include <ddk/ntddk.h>
15 #include <ntos/halfuncs.h>
16 #include <ddk/ntddblue.h>
17 #include <rosrtl/string.h>
25 /* DEFINITIONS ***************************************************************/
27 #define VIDMEM_BASE 0xb8000
29 #define CRTC_COMMAND ((PUCHAR)0x3d4)
30 #define CRTC_DATA ((PUCHAR)0x3d5)
32 #define CRTC_COLUMNS 0x01
33 #define CRTC_OVERFLOW 0x07
34 #define CRTC_ROWS 0x12
35 #define CRTC_SCANLINES 0x09
36 #define CRTC_CURSORSTART 0x0a
37 #define CRTC_CURSOREND 0x0b
38 #define CRTC_CURSORPOSHI 0x0e
39 #define CRTC_CURSORPOSLO 0x0f
41 #define ATTRC_WRITEREG ((PUCHAR)0x3c0)
42 #define ATTRC_READREG ((PUCHAR)0x3c1)
43 #define ATTRC_INPST1 ((PUCHAR)0x3da)
48 /* NOTES ******************************************************************/
50 * [[character][attribute]][[character][attribute]]....
54 /* TYPEDEFS ***************************************************************/
56 typedef struct _DEVICE_EXTENSION
58 PBYTE VideoMemory
; /* Pointer to video memory */
63 BYTE ScanLines
; /* Height of a text line */
64 WORD Rows
; /* Number of rows */
65 WORD Columns
; /* Number of columns */
66 } DEVICE_EXTENSION
, *PDEVICE_EXTENSION
;
69 /* FUNCTIONS **************************************************************/
72 ScrCreate(PDEVICE_OBJECT DeviceObject
,
75 PDEVICE_EXTENSION DeviceExtension
;
76 PHYSICAL_ADDRESS BaseAddress
;
81 DeviceExtension
= DeviceObject
->DeviceExtension
;
83 /* disable interrupts */
86 /* get current output position */
87 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSLO
);
88 offset
= READ_PORT_UCHAR (CRTC_DATA
);
89 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSHI
);
90 offset
+= (READ_PORT_UCHAR (CRTC_DATA
) << 8);
92 /* switch blinking characters off */
93 READ_PORT_UCHAR (ATTRC_INPST1
);
94 value
= READ_PORT_UCHAR (ATTRC_WRITEREG
);
95 WRITE_PORT_UCHAR (ATTRC_WRITEREG
, 0x10);
96 data
= READ_PORT_UCHAR (ATTRC_READREG
);
98 WRITE_PORT_UCHAR (ATTRC_WRITEREG
, data
);
99 WRITE_PORT_UCHAR (ATTRC_WRITEREG
, value
);
100 READ_PORT_UCHAR (ATTRC_INPST1
);
102 /* read screen information from crt controller */
103 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_COLUMNS
);
104 DeviceExtension
->Columns
= READ_PORT_UCHAR (CRTC_DATA
) + 1;
105 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_ROWS
);
106 DeviceExtension
->Rows
= READ_PORT_UCHAR (CRTC_DATA
);
107 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_OVERFLOW
);
108 data
= READ_PORT_UCHAR (CRTC_DATA
);
109 DeviceExtension
->Rows
|= (((data
& 0x02) << 7) | ((data
& 0x40) << 3));
110 DeviceExtension
->Rows
++;
111 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_SCANLINES
);
112 DeviceExtension
->ScanLines
= (READ_PORT_UCHAR (CRTC_DATA
) & 0x1F) + 1;
114 /* enable interrupts */
117 /* calculate number of text rows */
118 DeviceExtension
->Rows
=
119 DeviceExtension
->Rows
/ DeviceExtension
->ScanLines
;
121 DeviceExtension
->Rows
= 30;
124 DPRINT ("%d Columns %d Rows %d Scanlines\n",
125 DeviceExtension
->Columns
,
126 DeviceExtension
->Rows
,
127 DeviceExtension
->ScanLines
);
129 /* get pointer to video memory */
130 BaseAddress
.QuadPart
= VIDMEM_BASE
;
131 DeviceExtension
->VideoMemory
=
132 (PBYTE
)MmMapIoSpace (BaseAddress
, DeviceExtension
->Rows
* DeviceExtension
->Columns
* 2, MmNonCached
);
134 DeviceExtension
->CursorSize
= 5; /* FIXME: value correct?? */
135 DeviceExtension
->CursorVisible
= TRUE
;
137 /* more initialization */
138 DeviceExtension
->CharAttribute
= 0x17; /* light grey on blue */
139 DeviceExtension
->Mode
= ENABLE_PROCESSED_OUTPUT
|
140 ENABLE_WRAP_AT_EOL_OUTPUT
;
142 /* show blinking cursor */
144 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORSTART
);
145 WRITE_PORT_UCHAR (CRTC_DATA
, (DeviceExtension
->ScanLines
- 1) & 0x1F);
146 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSOREND
);
147 data
= READ_PORT_UCHAR (CRTC_DATA
) & 0xE0;
148 WRITE_PORT_UCHAR (CRTC_DATA
,
149 data
| ((DeviceExtension
->ScanLines
- 1) & 0x1F));
152 Status
= STATUS_SUCCESS
;
154 Irp
->IoStatus
.Status
= Status
;
155 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);
162 ScrWrite(PDEVICE_OBJECT DeviceObject
,
165 PIO_STACK_LOCATION stk
= IoGetCurrentIrpStackLocation (Irp
);
166 PDEVICE_EXTENSION DeviceExtension
= DeviceObject
->DeviceExtension
;
168 char *pch
= Irp
->UserBuffer
;
171 int cursorx
, cursory
;
173 int processed
= DeviceExtension
->Mode
& ENABLE_PROCESSED_OUTPUT
;
175 if (HalQueryDisplayOwnership())
177 /* Display is in graphics mode, we're not allowed to touch it */
178 Status
= STATUS_SUCCESS
;
180 Irp
->IoStatus
.Status
= Status
;
181 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);
186 vidmem
= DeviceExtension
->VideoMemory
;
187 rows
= DeviceExtension
->Rows
;
188 columns
= DeviceExtension
->Columns
;
191 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSHI
);
192 offset
= READ_PORT_UCHAR (CRTC_DATA
)<<8;
193 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSLO
);
194 offset
+= READ_PORT_UCHAR (CRTC_DATA
);
197 cursory
= offset
/ columns
;
198 cursorx
= offset
% columns
;
201 /* raw output mode */
202 memcpy( &vidmem
[(cursorx
* 2) + (cursory
* columns
* 2)], pch
, stk
->Parameters
.Write
.Length
);
203 offset
+= (stk
->Parameters
.Write
.Length
/ 2);
206 for (i
= 0; i
< stk
->Parameters
.Write
.Length
; i
++, pch
++)
215 else if (cursory
> 0)
217 cursorx
= columns
- 1;
220 vidmem
[(cursorx
* 2) + (cursory
* columns
* 2)] = ' ';
221 vidmem
[(cursorx
* 2) + (cursory
* columns
* 2) + 1] = (char) DeviceExtension
->CharAttribute
;
234 offset
= TAB_WIDTH
- (cursorx
% TAB_WIDTH
);
235 for (j
= 0; j
< offset
; j
++)
237 vidmem
[(cursorx
* 2) + (cursory
* columns
* 2)] = ' ';
240 if (cursorx
>= columns
)
249 vidmem
[(cursorx
* 2) + (cursory
* columns
* 2)] = *pch
;
250 vidmem
[(cursorx
* 2) + (cursory
* columns
* 2) + 1] = (char) DeviceExtension
->CharAttribute
;
252 if (cursorx
>= columns
)
261 unsigned short *LinePtr
;
264 &vidmem
[columns
* 2],
265 columns
* (rows
- 1) * 2);
267 LinePtr
= (unsigned short *) &vidmem
[columns
* (rows
- 1) * 2];
269 for (j
= 0; j
< columns
; j
++)
271 LinePtr
[j
] = DeviceExtension
->CharAttribute
<< 8;
274 for (j
= 0; j
< columns
; j
++)
276 vidmem
[(j
* 2) + (cursory
* columns
* 2)] = ' ';
277 vidmem
[(j
* 2) + (cursory
* columns
* 2) + 1] = (char)DeviceExtension
->CharAttribute
;
282 /* Set the cursor position */
283 offset
= (cursory
* columns
) + cursorx
;
286 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSLO
);
287 WRITE_PORT_UCHAR (CRTC_DATA
, offset
);
288 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSHI
);
290 WRITE_PORT_UCHAR (CRTC_DATA
, offset
);
293 Status
= STATUS_SUCCESS
;
295 Irp
->IoStatus
.Status
= Status
;
296 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);
303 ScrIoControl(PDEVICE_OBJECT DeviceObject
,
306 PIO_STACK_LOCATION stk
= IoGetCurrentIrpStackLocation (Irp
);
307 PDEVICE_EXTENSION DeviceExtension
;
310 DeviceExtension
= DeviceObject
->DeviceExtension
;
311 switch (stk
->Parameters
.DeviceIoControl
.IoControlCode
)
313 case IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO
:
315 PCONSOLE_SCREEN_BUFFER_INFO pcsbi
= (PCONSOLE_SCREEN_BUFFER_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
316 int rows
= DeviceExtension
->Rows
;
317 int columns
= DeviceExtension
->Columns
;
320 /* read cursor position from crtc */
322 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSLO
);
323 offset
= READ_PORT_UCHAR (CRTC_DATA
);
324 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSHI
);
325 offset
+= (READ_PORT_UCHAR (CRTC_DATA
) << 8);
328 pcsbi
->dwSize
.X
= columns
;
329 pcsbi
->dwSize
.Y
= rows
;
331 pcsbi
->dwCursorPosition
.X
= (SHORT
)(offset
% columns
);
332 pcsbi
->dwCursorPosition
.Y
= (SHORT
)(offset
/ columns
);
334 pcsbi
->wAttributes
= DeviceExtension
->CharAttribute
;
336 pcsbi
->srWindow
.Left
= 0;
337 pcsbi
->srWindow
.Right
= columns
- 1;
338 pcsbi
->srWindow
.Top
= 0;
339 pcsbi
->srWindow
.Bottom
= rows
- 1;
341 pcsbi
->dwMaximumWindowSize
.X
= columns
;
342 pcsbi
->dwMaximumWindowSize
.Y
= rows
;
344 Irp
->IoStatus
.Information
= sizeof (CONSOLE_SCREEN_BUFFER_INFO
);
345 Status
= STATUS_SUCCESS
;
349 case IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO
:
351 PCONSOLE_SCREEN_BUFFER_INFO pcsbi
= (PCONSOLE_SCREEN_BUFFER_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
354 DeviceExtension
->CharAttribute
= pcsbi
->wAttributes
;
355 offset
= (pcsbi
->dwCursorPosition
.Y
* DeviceExtension
->Columns
) +
356 pcsbi
->dwCursorPosition
.X
;
359 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSLO
);
360 WRITE_PORT_UCHAR (CRTC_DATA
, offset
);
361 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSHI
);
362 WRITE_PORT_UCHAR (CRTC_DATA
, offset
>>8);
365 Irp
->IoStatus
.Information
= 0;
366 Status
= STATUS_SUCCESS
;
370 case IOCTL_CONSOLE_GET_CURSOR_INFO
:
372 PCONSOLE_CURSOR_INFO pcci
= (PCONSOLE_CURSOR_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
374 pcci
->dwSize
= DeviceExtension
->CursorSize
;
375 pcci
->bVisible
= DeviceExtension
->CursorVisible
;
377 Irp
->IoStatus
.Information
= sizeof (CONSOLE_CURSOR_INFO
);
378 Status
= STATUS_SUCCESS
;
382 case IOCTL_CONSOLE_SET_CURSOR_INFO
:
384 PCONSOLE_CURSOR_INFO pcci
= (PCONSOLE_CURSOR_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
388 DeviceExtension
->CursorSize
= pcci
->dwSize
;
389 DeviceExtension
->CursorVisible
= pcci
->bVisible
;
390 height
= DeviceExtension
->ScanLines
;
391 data
= (pcci
->bVisible
) ? 0x00 : 0x20;
393 size
= (pcci
->dwSize
* height
) / 100;
399 data
|= (BYTE
)(height
- size
);
402 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORSTART
);
403 WRITE_PORT_UCHAR (CRTC_DATA
, data
);
404 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSOREND
);
405 value
= READ_PORT_UCHAR (CRTC_DATA
) & 0xE0;
406 WRITE_PORT_UCHAR (CRTC_DATA
, value
| (height
- 1));
410 Irp
->IoStatus
.Information
= 0;
411 Status
= STATUS_SUCCESS
;
415 case IOCTL_CONSOLE_GET_MODE
:
417 PCONSOLE_MODE pcm
= (PCONSOLE_MODE
)Irp
->AssociatedIrp
.SystemBuffer
;
419 pcm
->dwMode
= DeviceExtension
->Mode
;
421 Irp
->IoStatus
.Information
= sizeof(CONSOLE_MODE
);
422 Status
= STATUS_SUCCESS
;
426 case IOCTL_CONSOLE_SET_MODE
:
428 PCONSOLE_MODE pcm
= (PCONSOLE_MODE
)Irp
->AssociatedIrp
.SystemBuffer
;
430 DeviceExtension
->Mode
= pcm
->dwMode
;
432 Irp
->IoStatus
.Information
= 0;
433 Status
= STATUS_SUCCESS
;
437 case IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE
:
439 POUTPUT_ATTRIBUTE Buf
= (POUTPUT_ATTRIBUTE
)Irp
->AssociatedIrp
.SystemBuffer
;
444 vidmem
= DeviceExtension
->VideoMemory
;
445 offset
= (Buf
->dwCoord
.Y
* DeviceExtension
->Columns
* 2) +
446 (Buf
->dwCoord
.X
* 2) + 1;
448 for (dwCount
= 0; dwCount
< Buf
->nLength
; dwCount
++)
450 vidmem
[offset
+ (dwCount
* 2)] = (char) Buf
->wAttribute
;
453 Buf
->dwTransfered
= Buf
->nLength
;
455 Irp
->IoStatus
.Information
= 0;
456 Status
= STATUS_SUCCESS
;
460 case IOCTL_CONSOLE_READ_OUTPUT_ATTRIBUTE
:
462 POUTPUT_ATTRIBUTE Buf
= (POUTPUT_ATTRIBUTE
)Irp
->AssociatedIrp
.SystemBuffer
;
463 PWORD pAttr
= (PWORD
)MmGetSystemAddressForMdl(Irp
->MdlAddress
);
468 vidmem
= DeviceExtension
->VideoMemory
;
469 offset
= (Buf
->dwCoord
.Y
* DeviceExtension
->Columns
* 2) +
470 (Buf
->dwCoord
.X
* 2) + 1;
472 for (dwCount
= 0; dwCount
< stk
->Parameters
.DeviceIoControl
.OutputBufferLength
; dwCount
++, pAttr
++)
474 *((char *) pAttr
) = vidmem
[offset
+ (dwCount
* 2)];
477 Buf
->dwTransfered
= dwCount
;
479 Irp
->IoStatus
.Information
= sizeof(OUTPUT_ATTRIBUTE
);
480 Status
= STATUS_SUCCESS
;
484 case IOCTL_CONSOLE_WRITE_OUTPUT_ATTRIBUTE
:
486 COORD
*pCoord
= (COORD
*)MmGetSystemAddressForMdl(Irp
->MdlAddress
);
487 CHAR
*pAttr
= (CHAR
*)(pCoord
+ 1);
492 vidmem
= DeviceExtension
->VideoMemory
;
493 offset
= (pCoord
->Y
* DeviceExtension
->Columns
* 2) +
496 for (dwCount
= 0; dwCount
< (stk
->Parameters
.DeviceIoControl
.OutputBufferLength
- sizeof( COORD
)); dwCount
++, pAttr
++)
498 vidmem
[offset
+ (dwCount
* 2)] = *pAttr
;
500 Irp
->IoStatus
.Information
= 0;
501 Status
= STATUS_SUCCESS
;
505 case IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE
:
506 DeviceExtension
->CharAttribute
= (WORD
)*(PWORD
)Irp
->AssociatedIrp
.SystemBuffer
;
507 Irp
->IoStatus
.Information
= 0;
508 Status
= STATUS_SUCCESS
;
511 case IOCTL_CONSOLE_FILL_OUTPUT_CHARACTER
:
513 POUTPUT_CHARACTER Buf
= (POUTPUT_CHARACTER
)Irp
->AssociatedIrp
.SystemBuffer
;
518 vidmem
= DeviceExtension
->VideoMemory
;
519 offset
= (Buf
->dwCoord
.Y
* DeviceExtension
->Columns
* 2) +
520 (Buf
->dwCoord
.X
* 2);
524 for (dwCount
= 0; dwCount
< Buf
->nLength
; dwCount
++)
526 vidmem
[offset
+ (dwCount
* 2)] = (char) Buf
->cCharacter
;
529 Buf
->dwTransfered
= Buf
->nLength
;
531 Irp
->IoStatus
.Information
= 0;
532 Status
= STATUS_SUCCESS
;
536 case IOCTL_CONSOLE_READ_OUTPUT_CHARACTER
:
538 POUTPUT_CHARACTER Buf
= (POUTPUT_CHARACTER
)Irp
->AssociatedIrp
.SystemBuffer
;
539 LPSTR pChar
= (LPSTR
)MmGetSystemAddressForMdl(Irp
->MdlAddress
);
544 vidmem
= DeviceExtension
->VideoMemory
;
545 offset
= (Buf
->dwCoord
.Y
* DeviceExtension
->Columns
* 2) +
546 (Buf
->dwCoord
.X
* 2);
548 for (dwCount
= 0; dwCount
< stk
->Parameters
.DeviceIoControl
.OutputBufferLength
; dwCount
++, pChar
++)
550 *pChar
= vidmem
[offset
+ (dwCount
* 2)];
553 Buf
->dwTransfered
= dwCount
;
555 Irp
->IoStatus
.Information
= sizeof(OUTPUT_ATTRIBUTE
);
556 Status
= STATUS_SUCCESS
;
560 case IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER
:
568 pCoord
= (COORD
*)MmGetSystemAddressForMdl(Irp
->MdlAddress
);
569 pChar
= (CHAR
*)(pCoord
+ 1);
570 vidmem
= DeviceExtension
->VideoMemory
;
571 offset
= (pCoord
->Y
* DeviceExtension
->Columns
* 2) +
574 for (dwCount
= 0; dwCount
< (stk
->Parameters
.DeviceIoControl
.OutputBufferLength
- sizeof( COORD
)); dwCount
++, pChar
++)
576 vidmem
[offset
+ (dwCount
* 2)] = *pChar
;
579 Irp
->IoStatus
.Information
= 0;
580 Status
= STATUS_SUCCESS
;
584 case IOCTL_CONSOLE_DRAW
:
586 PCONSOLE_DRAW ConsoleDraw
;
588 UINT SrcDelta
, DestDelta
, i
, Offset
;
590 ConsoleDraw
= (PCONSOLE_DRAW
) MmGetSystemAddressForMdl(Irp
->MdlAddress
);
591 Src
= (PBYTE
) (ConsoleDraw
+ 1);
592 SrcDelta
= ConsoleDraw
->SizeX
* 2;
593 Dest
= DeviceExtension
->VideoMemory
+
594 (ConsoleDraw
->Y
* DeviceExtension
->Columns
+ ConsoleDraw
->X
) * 2;
595 DestDelta
= DeviceExtension
->Columns
* 2;
597 for (i
= 0; i
< ConsoleDraw
->SizeY
; i
++)
599 RtlCopyMemory(Dest
, Src
, SrcDelta
);
604 Offset
= (ConsoleDraw
->CursorY
* DeviceExtension
->Columns
) +
605 ConsoleDraw
->CursorX
;
608 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSLO
);
609 WRITE_PORT_UCHAR (CRTC_DATA
, Offset
);
610 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSHI
);
611 WRITE_PORT_UCHAR (CRTC_DATA
, Offset
>> 8);
614 Irp
->IoStatus
.Information
= 0;
615 Status
= STATUS_SUCCESS
;
620 Status
= STATUS_NOT_IMPLEMENTED
;
623 Irp
->IoStatus
.Status
= Status
;
624 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);
631 ScrDispatch(PDEVICE_OBJECT DeviceObject
,
634 PIO_STACK_LOCATION stk
= IoGetCurrentIrpStackLocation(Irp
);
637 switch (stk
->MajorFunction
)
640 Status
= STATUS_SUCCESS
;
644 Status
= STATUS_NOT_IMPLEMENTED
;
649 Irp
->IoStatus
.Status
= Status
;
650 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);
660 DriverEntry (PDRIVER_OBJECT DriverObject
, PUNICODE_STRING RegistryPath
)
662 PDEVICE_OBJECT DeviceObject
;
663 UNICODE_STRING DeviceName
= ROS_STRING_INITIALIZER(L
"\\Device\\BlueScreen");
664 UNICODE_STRING SymlinkName
= ROS_STRING_INITIALIZER(L
"\\??\\BlueScreen");
666 DPRINT ("Screen Driver 0.0.6\n");
668 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = ScrCreate
;
669 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = ScrDispatch
;
670 DriverObject
->MajorFunction
[IRP_MJ_READ
] = ScrDispatch
;
671 DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = ScrWrite
;
672 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = ScrIoControl
;
674 IoCreateDevice (DriverObject
,
675 sizeof(DEVICE_EXTENSION
),
682 IoCreateSymbolicLink (&SymlinkName
, &DeviceName
);
684 return (STATUS_SUCCESS
);