1 /* $Id: blue.c,v 1.20 2000/02/24 13:16:40 ekohl Exp $
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 <ddk/ntddblue.h>
20 #include <internal/debug.h>
23 /* DEFINITIONS ***************************************************************/
25 #define VIDMEM_BASE 0xb8000
26 #define VIDMEM_SIZE 0x2000
28 #define CRTC_COMMAND ((PUCHAR)0x3d4)
29 #define CRTC_DATA ((PUCHAR)0x3d5)
31 #define CRTC_COLUMNS 0x01
32 #define CRTC_OVERFLOW 0x07
33 #define CRTC_ROWS 0x12
34 #define CRTC_SCANLINES 0x09
35 #define CRTC_CURSORSTART 0x0a
36 #define CRTC_CURSOREND 0x0b
37 #define CRTC_CURSORPOSHI 0x0e
38 #define CRTC_CURSORPOSLO 0x0f
40 #define ATTRC_WRITEREG ((PUCHAR)0x3c0)
41 #define ATTRC_READREG ((PUCHAR)0x3c1)
42 #define ATTRC_INPST1 ((PUCHAR)0x3da)
47 /* NOTES ******************************************************************/
49 * [[character][attribute]][[character][attribute]]....
53 /* TYPEDEFS ***************************************************************/
55 typedef struct _DEVICE_EXTENSION
57 PBYTE VideoMemory
; /* Pointer to video memory */
62 BYTE ScanLines
; /* Height of a text line */
63 WORD Rows
; /* Number of rows */
64 WORD Columns
; /* Number of columns */
65 } DEVICE_EXTENSION
, *PDEVICE_EXTENSION
;
68 /* FUNCTIONS **************************************************************/
71 ScrCreate (PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
73 PDEVICE_EXTENSION DeviceExtension
;
74 PHYSICAL_ADDRESS BaseAddress
;
79 DeviceExtension
= DeviceObject
->DeviceExtension
;
81 /* get pointer to video memory */
82 BaseAddress
.QuadPart
= VIDMEM_BASE
;
83 DeviceExtension
->VideoMemory
=
84 (PBYTE
)MmMapIoSpace (BaseAddress
, VIDMEM_SIZE
, FALSE
);
86 /* disable interrupts */
89 /* get current output position */
90 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSLO
);
91 offset
= READ_PORT_UCHAR (CRTC_DATA
);
92 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSHI
);
93 offset
+= (READ_PORT_UCHAR (CRTC_DATA
) << 8);
95 /* switch blinking characters off */
96 READ_PORT_UCHAR (ATTRC_INPST1
);
97 value
= READ_PORT_UCHAR (ATTRC_WRITEREG
);
98 WRITE_PORT_UCHAR (ATTRC_WRITEREG
, 0x10);
99 data
= READ_PORT_UCHAR (ATTRC_READREG
);
101 WRITE_PORT_UCHAR (ATTRC_WRITEREG
, data
);
102 WRITE_PORT_UCHAR (ATTRC_WRITEREG
, value
);
103 READ_PORT_UCHAR (ATTRC_INPST1
);
105 /* read screen information from crt controller */
106 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_COLUMNS
);
107 DeviceExtension
->Columns
= READ_PORT_UCHAR (CRTC_DATA
) + 1;
108 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_ROWS
);
109 DeviceExtension
->Rows
= READ_PORT_UCHAR (CRTC_DATA
);
110 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_OVERFLOW
);
111 data
= READ_PORT_UCHAR (CRTC_DATA
);
112 DeviceExtension
->Rows
|= (((data
& 0x02) << 7) | ((data
& 0x40) << 3));
113 DeviceExtension
->Rows
++;
114 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_SCANLINES
);
115 DeviceExtension
->ScanLines
= (READ_PORT_UCHAR (CRTC_DATA
) & 0x1F) + 1;
117 /* enable interrupts */
120 /* calculate number of text rows */
121 DeviceExtension
->Rows
=
122 DeviceExtension
->Rows
/ DeviceExtension
->ScanLines
;
124 DPRINT ("%d Columns %d Rows %d Scanlines\n",
125 DeviceExtension
->Columns
,
126 DeviceExtension
->Rows
,
127 DeviceExtension
->ScanLines
);
129 DeviceExtension
->CursorSize
= 5; /* FIXME: value correct?? */
130 DeviceExtension
->CursorVisible
= TRUE
;
132 /* more initialization */
133 DeviceExtension
->CharAttribute
= 0x17; /* light grey on blue */
134 DeviceExtension
->Mode
= ENABLE_PROCESSED_OUTPUT
|
135 ENABLE_WRAP_AT_EOL_OUTPUT
;
137 /* show blinking cursor */
139 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORSTART
);
140 WRITE_PORT_UCHAR (CRTC_DATA
, (DeviceExtension
->ScanLines
- 1) & 0x1F);
141 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSOREND
);
142 data
= READ_PORT_UCHAR (CRTC_DATA
) & 0xE0;
143 WRITE_PORT_UCHAR (CRTC_DATA
,
144 data
| ((DeviceExtension
->ScanLines
- 1) & 0x1F));
147 Status
= STATUS_SUCCESS
;
149 Irp
->IoStatus
.Status
= Status
;
150 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);
157 ScrWrite (PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
159 PIO_STACK_LOCATION stk
= IoGetCurrentIrpStackLocation (Irp
);
160 PDEVICE_EXTENSION DeviceExtension
;
162 char *pch
= Irp
->UserBuffer
;
165 int cursorx
, cursory
;
168 DeviceExtension
= DeviceObject
->DeviceExtension
;
169 vidmem
= DeviceExtension
->VideoMemory
;
170 rows
= DeviceExtension
->Rows
;
171 columns
= DeviceExtension
->Columns
;
173 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSHI
);
174 offset
= READ_PORT_UCHAR (CRTC_DATA
)<<8;
175 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSLO
);
176 offset
+= READ_PORT_UCHAR (CRTC_DATA
);
178 cursory
= offset
/ columns
;
179 cursorx
= offset
% columns
;
181 for (i
= 0; i
< stk
->Parameters
.Write
.Length
; i
++, pch
++)
190 else if (cursory
> 0)
192 cursorx
= columns
- 1;
206 offset
= TAB_WIDTH
- (cursorx
% TAB_WIDTH
);
207 for (j
= 0; j
< offset
; j
++)
209 vidmem
[(cursorx
* 2) + (cursory
* columns
* 2)] = ' ';
212 if (cursorx
>= columns
)
221 vidmem
[(cursorx
* 2) + (cursory
* columns
* 2)] = *pch
;
222 vidmem
[(cursorx
* 2) + (cursory
* columns
* 2) + 1] = (char) DeviceExtension
->CharAttribute
;
224 if (cursorx
>= columns
)
234 unsigned short *LinePtr
;
237 &vidmem
[columns
* 2],
238 columns
* (rows
- 1) * 2);
240 LinePtr
= (unsigned short *) &vidmem
[columns
* (rows
- 1) * 2];
242 for (j
= 0; j
< columns
; j
++)
244 LinePtr
[j
] = DeviceExtension
->CharAttribute
<< 8;
247 for (j
= 0; j
< columns
; j
++)
249 vidmem
[(j
* 2) + (cursory
* columns
* 2)] = ' ';
250 vidmem
[(j
* 2) + (cursory
* columns
* 2) + 1] = (char)DeviceExtension
->CharAttribute
;
255 /* Set the cursor position */
256 offset
= (cursory
* columns
) + cursorx
;
258 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSLO
);
259 WRITE_PORT_UCHAR (CRTC_DATA
, offset
);
260 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSHI
);
262 WRITE_PORT_UCHAR (CRTC_DATA
, offset
);
264 Status
= STATUS_SUCCESS
;
266 Irp
->IoStatus
.Status
= Status
;
267 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);
274 ScrIoControl (PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
276 PIO_STACK_LOCATION stk
= IoGetCurrentIrpStackLocation (Irp
);
277 PDEVICE_EXTENSION DeviceExtension
;
280 DeviceExtension
= DeviceObject
->DeviceExtension
;
282 switch (stk
->Parameters
.DeviceIoControl
.IoControlCode
)
284 case IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO
:
286 PCONSOLE_SCREEN_BUFFER_INFO pcsbi
= (PCONSOLE_SCREEN_BUFFER_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
287 int rows
= DeviceExtension
->Rows
;
288 int columns
= DeviceExtension
->Columns
;
291 /* read cursor position from crtc */
293 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSLO
);
294 offset
= READ_PORT_UCHAR (CRTC_DATA
);
295 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSHI
);
296 offset
+= (READ_PORT_UCHAR (CRTC_DATA
) << 8);
299 pcsbi
->dwSize
.X
= rows
;
300 pcsbi
->dwSize
.Y
= columns
;
302 pcsbi
->dwCursorPosition
.X
= (SHORT
)(offset
% columns
);
303 pcsbi
->dwCursorPosition
.Y
= (SHORT
)(offset
/ columns
);
305 pcsbi
->wAttributes
= DeviceExtension
->CharAttribute
;
307 pcsbi
->srWindow
.Left
= 0;
308 pcsbi
->srWindow
.Right
= columns
- 1;
309 pcsbi
->srWindow
.Top
= 0;
310 pcsbi
->srWindow
.Bottom
= rows
- 1;
312 pcsbi
->dwMaximumWindowSize
.X
= columns
;
313 pcsbi
->dwMaximumWindowSize
.Y
= rows
;
315 Irp
->IoStatus
.Information
= sizeof (CONSOLE_SCREEN_BUFFER_INFO
);
316 Status
= STATUS_SUCCESS
;
320 case IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO
:
322 PCONSOLE_SCREEN_BUFFER_INFO pcsbi
= (PCONSOLE_SCREEN_BUFFER_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
325 DeviceExtension
->CharAttribute
= pcsbi
->wAttributes
;
327 offset
= (pcsbi
->dwCursorPosition
.Y
* DeviceExtension
->Columns
) +
328 pcsbi
->dwCursorPosition
.X
;
331 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSLO
);
332 WRITE_PORT_UCHAR (CRTC_DATA
, offset
);
333 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSHI
);
334 WRITE_PORT_UCHAR (CRTC_DATA
, offset
>>8);
337 Irp
->IoStatus
.Information
= 0;
338 Status
= STATUS_SUCCESS
;
342 case IOCTL_CONSOLE_GET_CURSOR_INFO
:
344 PCONSOLE_CURSOR_INFO pcci
= (PCONSOLE_CURSOR_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
346 pcci
->dwSize
= DeviceExtension
->CursorSize
;
347 pcci
->bVisible
= DeviceExtension
->CursorVisible
;
349 Irp
->IoStatus
.Information
= sizeof (CONSOLE_CURSOR_INFO
);
350 Status
= STATUS_SUCCESS
;
354 case IOCTL_CONSOLE_SET_CURSOR_INFO
:
356 PCONSOLE_CURSOR_INFO pcci
= (PCONSOLE_CURSOR_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
360 DeviceExtension
->CursorSize
= pcci
->dwSize
;
361 DeviceExtension
->CursorVisible
= pcci
->bVisible
;
362 height
= DeviceExtension
->ScanLines
;
363 data
= (pcci
->bVisible
) ? 0x40 : 0x20;
365 size
= (pcci
->dwSize
* height
) / 100;
369 data
|= (BYTE
)(height
- size
);
372 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORSTART
);
373 WRITE_PORT_UCHAR (CRTC_DATA
, data
);
374 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSOREND
);
375 value
= READ_PORT_UCHAR (CRTC_DATA
) & 0xE0;
376 WRITE_PORT_UCHAR (CRTC_DATA
, value
| (height
- 1));
380 Irp
->IoStatus
.Information
= 0;
381 Status
= STATUS_SUCCESS
;
385 case IOCTL_CONSOLE_GET_MODE
:
387 PCONSOLE_MODE pcm
= (PCONSOLE_MODE
)Irp
->AssociatedIrp
.SystemBuffer
;
389 pcm
->dwMode
= DeviceExtension
->Mode
;
391 Irp
->IoStatus
.Information
= sizeof(CONSOLE_MODE
);
392 Status
= STATUS_SUCCESS
;
396 case IOCTL_CONSOLE_SET_MODE
:
398 PCONSOLE_MODE pcm
= (PCONSOLE_MODE
)Irp
->AssociatedIrp
.SystemBuffer
;
400 DeviceExtension
->Mode
= pcm
->dwMode
;
402 Irp
->IoStatus
.Information
= 0;
403 Status
= STATUS_SUCCESS
;
407 case IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE
:
409 POUTPUT_ATTRIBUTE Buf
= (POUTPUT_ATTRIBUTE
)Irp
->AssociatedIrp
.SystemBuffer
;
414 vidmem
= DeviceExtension
->VideoMemory
;
415 offset
= (Buf
->dwCoord
.Y
* DeviceExtension
->Columns
* 2) +
416 (Buf
->dwCoord
.X
* 2) + 1;
418 for (dwCount
= 0; dwCount
< Buf
->nLength
; dwCount
++)
420 vidmem
[offset
+ (dwCount
* 2)] = (char) Buf
->wAttribute
;
423 Buf
->dwTransfered
= Buf
->nLength
;
425 Irp
->IoStatus
.Information
= 0;
426 Status
= STATUS_SUCCESS
;
430 case IOCTL_CONSOLE_READ_OUTPUT_ATTRIBUTE
:
432 POUTPUT_ATTRIBUTE Buf
= (POUTPUT_ATTRIBUTE
)Irp
->AssociatedIrp
.SystemBuffer
;
433 LPWORD pAttr
= (LPWORD
)MmGetSystemAddressForMdl(Irp
->MdlAddress
);
438 vidmem
= DeviceExtension
->VideoMemory
;
439 offset
= (Buf
->dwCoord
.Y
* DeviceExtension
->Columns
* 2) +
440 (Buf
->dwCoord
.X
* 2) + 1;
442 for (dwCount
= 0; dwCount
< stk
->Parameters
.Write
.Length
; dwCount
++, pAttr
++)
444 (char) *pAttr
= vidmem
[offset
+ (dwCount
* 2)];
447 Buf
->dwTransfered
= dwCount
;
449 Irp
->IoStatus
.Information
= sizeof(OUTPUT_ATTRIBUTE
);
450 Status
= STATUS_SUCCESS
;
454 case IOCTL_CONSOLE_WRITE_OUTPUT_ATTRIBUTE
:
456 POUTPUT_ATTRIBUTE Buf
= (POUTPUT_ATTRIBUTE
)Irp
->AssociatedIrp
.SystemBuffer
;
457 LPWORD pAttr
= (LPWORD
)MmGetSystemAddressForMdl(Irp
->MdlAddress
);
462 vidmem
= DeviceExtension
->VideoMemory
;
463 offset
= (Buf
->dwCoord
.Y
* DeviceExtension
->Columns
* 2) +
464 (Buf
->dwCoord
.X
* 2) + 1;
466 for (dwCount
= 0; dwCount
< stk
->Parameters
.Write
.Length
; dwCount
++, pAttr
++)
468 vidmem
[offset
+ (dwCount
* 2)] = (char) *pAttr
;
471 Buf
->dwTransfered
= dwCount
;
473 Irp
->IoStatus
.Information
= sizeof(OUTPUT_ATTRIBUTE
);
474 Status
= STATUS_SUCCESS
;
478 case IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE
:
479 DeviceExtension
->CharAttribute
= (WORD
)*(LPWORD
)Irp
->AssociatedIrp
.SystemBuffer
;
480 Irp
->IoStatus
.Information
= 0;
481 Status
= STATUS_SUCCESS
;
485 case IOCTL_CONSOLE_FILL_OUTPUT_CHARACTER
:
487 POUTPUT_CHARACTER Buf
= (POUTPUT_CHARACTER
)Irp
->AssociatedIrp
.SystemBuffer
;
492 vidmem
= DeviceExtension
->VideoMemory
;
493 offset
= (Buf
->dwCoord
.Y
* DeviceExtension
->Columns
* 2) +
494 (Buf
->dwCoord
.X
* 2);
498 for (dwCount
= 0; dwCount
< Buf
->nLength
; dwCount
++)
500 vidmem
[offset
+ (dwCount
* 2)] = (char) Buf
->cCharacter
;
503 Buf
->dwTransfered
= Buf
->nLength
;
505 Irp
->IoStatus
.Information
= 0;
506 Status
= STATUS_SUCCESS
;
510 case IOCTL_CONSOLE_READ_OUTPUT_CHARACTER
:
512 POUTPUT_CHARACTER Buf
= (POUTPUT_CHARACTER
)Irp
->AssociatedIrp
.SystemBuffer
;
513 LPSTR pChar
= (LPSTR
)MmGetSystemAddressForMdl(Irp
->MdlAddress
);
518 vidmem
= DeviceExtension
->VideoMemory
;
519 offset
= (Buf
->dwCoord
.Y
* DeviceExtension
->Columns
* 2) +
520 (Buf
->dwCoord
.X
* 2);
522 for (dwCount
= 0; dwCount
< stk
->Parameters
.Write
.Length
; dwCount
++, pChar
++)
524 *pChar
= vidmem
[offset
+ (dwCount
* 2)];
527 Buf
->dwTransfered
= dwCount
;
529 Irp
->IoStatus
.Information
= sizeof(OUTPUT_ATTRIBUTE
);
530 Status
= STATUS_SUCCESS
;
534 case IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER
:
536 POUTPUT_CHARACTER Buf
= (POUTPUT_CHARACTER
)Irp
->AssociatedIrp
.SystemBuffer
;
537 LPSTR pChar
= (LPSTR
)MmGetSystemAddressForMdl(Irp
->MdlAddress
);
542 vidmem
= DeviceExtension
->VideoMemory
;
543 offset
= (Buf
->dwCoord
.Y
* DeviceExtension
->Columns
* 2) +
544 (Buf
->dwCoord
.X
* 2) + 1;
546 for (dwCount
= 0; dwCount
< stk
->Parameters
.Write
.Length
; dwCount
++, pChar
++)
548 vidmem
[offset
+ (dwCount
* 2)] = (char) *pChar
;
551 Buf
->dwTransfered
= dwCount
;
553 Irp
->IoStatus
.Information
= sizeof(OUTPUT_ATTRIBUTE
);
554 Status
= STATUS_SUCCESS
;
560 Status
= STATUS_NOT_IMPLEMENTED
;
563 Irp
->IoStatus
.Status
= Status
;
564 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);
571 ScrDispatch (PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
573 PIO_STACK_LOCATION stk
= IoGetCurrentIrpStackLocation(Irp
);
576 switch (stk
->MajorFunction
)
579 Status
= STATUS_SUCCESS
;
583 Status
= STATUS_NOT_IMPLEMENTED
;
588 Irp
->IoStatus
.Status
= Status
;
589 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);
599 DriverEntry (PDRIVER_OBJECT DriverObject
, PUNICODE_STRING RegistryPath
)
601 PDEVICE_OBJECT DeviceObject
;
602 ANSI_STRING adevice_name
;
603 UNICODE_STRING device_name
;
604 ANSI_STRING asymlink_name
;
605 UNICODE_STRING symlink_name
;
607 DbgPrint ("Screen Driver 0.0.6\n");
609 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = ScrCreate
;
610 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = ScrDispatch
;
611 DriverObject
->MajorFunction
[IRP_MJ_READ
] = ScrDispatch
;
612 DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = ScrWrite
;
613 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = ScrIoControl
;
615 RtlInitAnsiString (&adevice_name
, "\\Device\\BlueScreen");
616 RtlAnsiStringToUnicodeString (&device_name
, &adevice_name
, TRUE
);
617 IoCreateDevice (DriverObject
,
618 sizeof(DEVICE_EXTENSION
),
625 RtlInitAnsiString (&asymlink_name
, "\\??\\BlueScreen");
626 RtlAnsiStringToUnicodeString (&symlink_name
, &asymlink_name
, TRUE
);
627 IoCreateSymbolicLink (&symlink_name
, &device_name
);
629 RtlFreeUnicodeString (&device_name
);
630 RtlFreeUnicodeString (&symlink_name
);
632 return (STATUS_SUCCESS
);