1 /* $Id: blue.c,v 1.40 2003/07/12 10:24:45 chorns 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 ******************************************************************/
15 #include <ddk/ntddblue.h>
23 /* DEFINITIONS ***************************************************************/
25 #define VIDMEM_BASE 0xb8000
27 #define CRTC_COMMAND ((PUCHAR)0x3d4)
28 #define CRTC_DATA ((PUCHAR)0x3d5)
30 #define CRTC_COLUMNS 0x01
31 #define CRTC_OVERFLOW 0x07
32 #define CRTC_ROWS 0x12
33 #define CRTC_SCANLINES 0x09
34 #define CRTC_CURSORSTART 0x0a
35 #define CRTC_CURSOREND 0x0b
36 #define CRTC_CURSORPOSHI 0x0e
37 #define CRTC_CURSORPOSLO 0x0f
39 #define ATTRC_WRITEREG ((PUCHAR)0x3c0)
40 #define ATTRC_READREG ((PUCHAR)0x3c1)
41 #define ATTRC_INPST1 ((PUCHAR)0x3da)
46 /* NOTES ******************************************************************/
48 * [[character][attribute]][[character][attribute]]....
52 /* TYPEDEFS ***************************************************************/
54 typedef struct _DEVICE_EXTENSION
56 PBYTE VideoMemory
; /* Pointer to video memory */
61 BYTE ScanLines
; /* Height of a text line */
62 WORD Rows
; /* Number of rows */
63 WORD Columns
; /* Number of columns */
64 } DEVICE_EXTENSION
, *PDEVICE_EXTENSION
;
67 /* FUNCTIONS **************************************************************/
70 ScrCreate(PDEVICE_OBJECT DeviceObject
,
73 PDEVICE_EXTENSION DeviceExtension
;
74 PHYSICAL_ADDRESS BaseAddress
;
79 DeviceExtension
= DeviceObject
->DeviceExtension
;
81 /* disable interrupts */
84 /* get current output position */
85 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSLO
);
86 offset
= READ_PORT_UCHAR (CRTC_DATA
);
87 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSHI
);
88 offset
+= (READ_PORT_UCHAR (CRTC_DATA
) << 8);
90 /* switch blinking characters off */
91 READ_PORT_UCHAR (ATTRC_INPST1
);
92 value
= READ_PORT_UCHAR (ATTRC_WRITEREG
);
93 WRITE_PORT_UCHAR (ATTRC_WRITEREG
, 0x10);
94 data
= READ_PORT_UCHAR (ATTRC_READREG
);
96 WRITE_PORT_UCHAR (ATTRC_WRITEREG
, data
);
97 WRITE_PORT_UCHAR (ATTRC_WRITEREG
, value
);
98 READ_PORT_UCHAR (ATTRC_INPST1
);
100 /* read screen information from crt controller */
101 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_COLUMNS
);
102 DeviceExtension
->Columns
= READ_PORT_UCHAR (CRTC_DATA
) + 1;
103 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_ROWS
);
104 DeviceExtension
->Rows
= READ_PORT_UCHAR (CRTC_DATA
);
105 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_OVERFLOW
);
106 data
= READ_PORT_UCHAR (CRTC_DATA
);
107 DeviceExtension
->Rows
|= (((data
& 0x02) << 7) | ((data
& 0x40) << 3));
108 DeviceExtension
->Rows
++;
109 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_SCANLINES
);
110 DeviceExtension
->ScanLines
= (READ_PORT_UCHAR (CRTC_DATA
) & 0x1F) + 1;
112 /* enable interrupts */
115 /* calculate number of text rows */
116 DeviceExtension
->Rows
=
117 DeviceExtension
->Rows
/ DeviceExtension
->ScanLines
;
119 DeviceExtension
->Rows
= 30;
122 DPRINT ("%d Columns %d Rows %d Scanlines\n",
123 DeviceExtension
->Columns
,
124 DeviceExtension
->Rows
,
125 DeviceExtension
->ScanLines
);
127 /* get pointer to video memory */
128 BaseAddress
.QuadPart
= VIDMEM_BASE
;
129 DeviceExtension
->VideoMemory
=
130 (PBYTE
)MmMapIoSpace (BaseAddress
, DeviceExtension
->Rows
* DeviceExtension
->Columns
* 2, FALSE
);
132 DeviceExtension
->CursorSize
= 5; /* FIXME: value correct?? */
133 DeviceExtension
->CursorVisible
= TRUE
;
135 /* more initialization */
136 DeviceExtension
->CharAttribute
= 0x17; /* light grey on blue */
137 DeviceExtension
->Mode
= ENABLE_PROCESSED_OUTPUT
|
138 ENABLE_WRAP_AT_EOL_OUTPUT
;
140 /* show blinking cursor */
142 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORSTART
);
143 WRITE_PORT_UCHAR (CRTC_DATA
, (DeviceExtension
->ScanLines
- 1) & 0x1F);
144 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSOREND
);
145 data
= READ_PORT_UCHAR (CRTC_DATA
) & 0xE0;
146 WRITE_PORT_UCHAR (CRTC_DATA
,
147 data
| ((DeviceExtension
->ScanLines
- 1) & 0x1F));
150 Status
= STATUS_SUCCESS
;
152 Irp
->IoStatus
.Status
= Status
;
153 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);
160 ScrWrite(PDEVICE_OBJECT DeviceObject
,
163 PIO_STACK_LOCATION stk
= IoGetCurrentIrpStackLocation (Irp
);
164 PDEVICE_EXTENSION DeviceExtension
= DeviceObject
->DeviceExtension
;
166 char *pch
= Irp
->UserBuffer
;
169 int cursorx
, cursory
;
171 int processed
= DeviceExtension
->Mode
& ENABLE_PROCESSED_OUTPUT
;
173 if (HalQueryDisplayOwnership())
175 /* Display is in graphics mode, we're not allowed to touch it */
176 Status
= STATUS_SUCCESS
;
178 Irp
->IoStatus
.Status
= Status
;
179 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);
184 vidmem
= DeviceExtension
->VideoMemory
;
185 rows
= DeviceExtension
->Rows
;
186 columns
= DeviceExtension
->Columns
;
189 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSHI
);
190 offset
= READ_PORT_UCHAR (CRTC_DATA
)<<8;
191 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSLO
);
192 offset
+= READ_PORT_UCHAR (CRTC_DATA
);
195 cursory
= offset
/ columns
;
196 cursorx
= offset
% columns
;
199 /* raw output mode */
200 memcpy( &vidmem
[(cursorx
* 2) + (cursory
* columns
* 2)], pch
, stk
->Parameters
.Write
.Length
);
201 offset
+= (stk
->Parameters
.Write
.Length
/ 2);
204 for (i
= 0; i
< stk
->Parameters
.Write
.Length
; i
++, pch
++)
213 else if (cursory
> 0)
215 cursorx
= columns
- 1;
218 vidmem
[(cursorx
* 2) + (cursory
* columns
* 2)] = ' ';
219 vidmem
[(cursorx
* 2) + (cursory
* columns
* 2) + 1] = (char) DeviceExtension
->CharAttribute
;
232 offset
= TAB_WIDTH
- (cursorx
% TAB_WIDTH
);
233 for (j
= 0; j
< offset
; j
++)
235 vidmem
[(cursorx
* 2) + (cursory
* columns
* 2)] = ' ';
238 if (cursorx
>= columns
)
247 vidmem
[(cursorx
* 2) + (cursory
* columns
* 2)] = *pch
;
248 vidmem
[(cursorx
* 2) + (cursory
* columns
* 2) + 1] = (char) DeviceExtension
->CharAttribute
;
250 if (cursorx
>= columns
)
259 unsigned short *LinePtr
;
262 &vidmem
[columns
* 2],
263 columns
* (rows
- 1) * 2);
265 LinePtr
= (unsigned short *) &vidmem
[columns
* (rows
- 1) * 2];
267 for (j
= 0; j
< columns
; j
++)
269 LinePtr
[j
] = DeviceExtension
->CharAttribute
<< 8;
272 for (j
= 0; j
< columns
; j
++)
274 vidmem
[(j
* 2) + (cursory
* columns
* 2)] = ' ';
275 vidmem
[(j
* 2) + (cursory
* columns
* 2) + 1] = (char)DeviceExtension
->CharAttribute
;
280 /* Set the cursor position */
281 offset
= (cursory
* columns
) + cursorx
;
284 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSLO
);
285 WRITE_PORT_UCHAR (CRTC_DATA
, offset
);
286 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSHI
);
288 WRITE_PORT_UCHAR (CRTC_DATA
, offset
);
291 Status
= STATUS_SUCCESS
;
293 Irp
->IoStatus
.Status
= Status
;
294 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);
301 ScrIoControl(PDEVICE_OBJECT DeviceObject
,
304 PIO_STACK_LOCATION stk
= IoGetCurrentIrpStackLocation (Irp
);
305 PDEVICE_EXTENSION DeviceExtension
;
307 DeviceExtension
= DeviceObject
->DeviceExtension
;
308 switch (stk
->Parameters
.DeviceIoControl
.IoControlCode
)
310 case IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO
:
312 PCONSOLE_SCREEN_BUFFER_INFO pcsbi
= (PCONSOLE_SCREEN_BUFFER_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
313 int rows
= DeviceExtension
->Rows
;
314 int columns
= DeviceExtension
->Columns
;
317 /* read cursor position from crtc */
319 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSLO
);
320 offset
= READ_PORT_UCHAR (CRTC_DATA
);
321 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSHI
);
322 offset
+= (READ_PORT_UCHAR (CRTC_DATA
) << 8);
325 pcsbi
->dwSize
.X
= columns
;
326 pcsbi
->dwSize
.Y
= rows
;
328 pcsbi
->dwCursorPosition
.X
= (SHORT
)(offset
% columns
);
329 pcsbi
->dwCursorPosition
.Y
= (SHORT
)(offset
/ columns
);
331 pcsbi
->wAttributes
= DeviceExtension
->CharAttribute
;
333 pcsbi
->srWindow
.Left
= 0;
334 pcsbi
->srWindow
.Right
= columns
- 1;
335 pcsbi
->srWindow
.Top
= 0;
336 pcsbi
->srWindow
.Bottom
= rows
- 1;
338 pcsbi
->dwMaximumWindowSize
.X
= columns
;
339 pcsbi
->dwMaximumWindowSize
.Y
= rows
;
341 Irp
->IoStatus
.Information
= sizeof (CONSOLE_SCREEN_BUFFER_INFO
);
342 Status
= STATUS_SUCCESS
;
346 case IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO
:
348 PCONSOLE_SCREEN_BUFFER_INFO pcsbi
= (PCONSOLE_SCREEN_BUFFER_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
351 DeviceExtension
->CharAttribute
= pcsbi
->wAttributes
;
352 offset
= (pcsbi
->dwCursorPosition
.Y
* DeviceExtension
->Columns
) +
353 pcsbi
->dwCursorPosition
.X
;
356 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSLO
);
357 WRITE_PORT_UCHAR (CRTC_DATA
, offset
);
358 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSHI
);
359 WRITE_PORT_UCHAR (CRTC_DATA
, offset
>>8);
362 Irp
->IoStatus
.Information
= 0;
363 Status
= STATUS_SUCCESS
;
367 case IOCTL_CONSOLE_GET_CURSOR_INFO
:
369 PCONSOLE_CURSOR_INFO pcci
= (PCONSOLE_CURSOR_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
371 pcci
->dwSize
= DeviceExtension
->CursorSize
;
372 pcci
->bVisible
= DeviceExtension
->CursorVisible
;
374 Irp
->IoStatus
.Information
= sizeof (CONSOLE_CURSOR_INFO
);
375 Status
= STATUS_SUCCESS
;
379 case IOCTL_CONSOLE_SET_CURSOR_INFO
:
381 PCONSOLE_CURSOR_INFO pcci
= (PCONSOLE_CURSOR_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
385 DeviceExtension
->CursorSize
= pcci
->dwSize
;
386 DeviceExtension
->CursorVisible
= pcci
->bVisible
;
387 height
= DeviceExtension
->ScanLines
;
388 data
= (pcci
->bVisible
) ? 0x40 : 0x20;
390 size
= (pcci
->dwSize
* height
) / 100;
394 data
|= (BYTE
)(height
- size
);
397 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORSTART
);
398 WRITE_PORT_UCHAR (CRTC_DATA
, data
);
399 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSOREND
);
400 value
= READ_PORT_UCHAR (CRTC_DATA
) & 0xE0;
401 WRITE_PORT_UCHAR (CRTC_DATA
, value
| (height
- 1));
405 Irp
->IoStatus
.Information
= 0;
406 Status
= STATUS_SUCCESS
;
410 case IOCTL_CONSOLE_GET_MODE
:
412 PCONSOLE_MODE pcm
= (PCONSOLE_MODE
)Irp
->AssociatedIrp
.SystemBuffer
;
414 pcm
->dwMode
= DeviceExtension
->Mode
;
416 Irp
->IoStatus
.Information
= sizeof(CONSOLE_MODE
);
417 Status
= STATUS_SUCCESS
;
421 case IOCTL_CONSOLE_SET_MODE
:
423 PCONSOLE_MODE pcm
= (PCONSOLE_MODE
)Irp
->AssociatedIrp
.SystemBuffer
;
425 DeviceExtension
->Mode
= pcm
->dwMode
;
427 Irp
->IoStatus
.Information
= 0;
428 Status
= STATUS_SUCCESS
;
432 case IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE
:
434 POUTPUT_ATTRIBUTE Buf
= (POUTPUT_ATTRIBUTE
)Irp
->AssociatedIrp
.SystemBuffer
;
439 vidmem
= DeviceExtension
->VideoMemory
;
440 offset
= (Buf
->dwCoord
.Y
* DeviceExtension
->Columns
* 2) +
441 (Buf
->dwCoord
.X
* 2) + 1;
443 for (dwCount
= 0; dwCount
< Buf
->nLength
; dwCount
++)
445 vidmem
[offset
+ (dwCount
* 2)] = (char) Buf
->wAttribute
;
448 Buf
->dwTransfered
= Buf
->nLength
;
450 Irp
->IoStatus
.Information
= 0;
451 Status
= STATUS_SUCCESS
;
455 case IOCTL_CONSOLE_READ_OUTPUT_ATTRIBUTE
:
457 POUTPUT_ATTRIBUTE Buf
= (POUTPUT_ATTRIBUTE
)Irp
->AssociatedIrp
.SystemBuffer
;
458 PWORD pAttr
= (PWORD
)MmGetSystemAddressForMdl(Irp
->MdlAddress
);
463 vidmem
= DeviceExtension
->VideoMemory
;
464 offset
= (Buf
->dwCoord
.Y
* DeviceExtension
->Columns
* 2) +
465 (Buf
->dwCoord
.X
* 2) + 1;
467 for (dwCount
= 0; dwCount
< stk
->Parameters
.DeviceIoControl
.OutputBufferLength
; dwCount
++, pAttr
++)
469 (char) *pAttr
= vidmem
[offset
+ (dwCount
* 2)];
472 Buf
->dwTransfered
= dwCount
;
474 Irp
->IoStatus
.Information
= sizeof(OUTPUT_ATTRIBUTE
);
475 Status
= STATUS_SUCCESS
;
479 case IOCTL_CONSOLE_WRITE_OUTPUT_ATTRIBUTE
:
481 COORD
*pCoord
= (COORD
*)MmGetSystemAddressForMdl(Irp
->MdlAddress
);
482 CHAR
*pAttr
= (CHAR
*)(pCoord
+ 1);
487 vidmem
= DeviceExtension
->VideoMemory
;
488 offset
= (pCoord
->Y
* DeviceExtension
->Columns
* 2) +
491 for (dwCount
= 0; dwCount
< (stk
->Parameters
.DeviceIoControl
.InputBufferLength
- sizeof( COORD
)); dwCount
++, pAttr
++)
493 vidmem
[offset
+ (dwCount
* 2)] = *pAttr
;
495 Irp
->IoStatus
.Information
= 0;
496 Status
= STATUS_SUCCESS
;
500 case IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE
:
501 DeviceExtension
->CharAttribute
= (WORD
)*(PWORD
)Irp
->AssociatedIrp
.SystemBuffer
;
502 Irp
->IoStatus
.Information
= 0;
503 Status
= STATUS_SUCCESS
;
507 case IOCTL_CONSOLE_FILL_OUTPUT_CHARACTER
:
509 POUTPUT_CHARACTER Buf
= (POUTPUT_CHARACTER
)Irp
->AssociatedIrp
.SystemBuffer
;
514 vidmem
= DeviceExtension
->VideoMemory
;
515 offset
= (Buf
->dwCoord
.Y
* DeviceExtension
->Columns
* 2) +
516 (Buf
->dwCoord
.X
* 2);
520 for (dwCount
= 0; dwCount
< Buf
->nLength
; dwCount
++)
522 vidmem
[offset
+ (dwCount
* 2)] = (char) Buf
->cCharacter
;
525 Buf
->dwTransfered
= Buf
->nLength
;
527 Irp
->IoStatus
.Information
= 0;
528 Status
= STATUS_SUCCESS
;
532 case IOCTL_CONSOLE_READ_OUTPUT_CHARACTER
:
534 POUTPUT_CHARACTER Buf
= (POUTPUT_CHARACTER
)Irp
->AssociatedIrp
.SystemBuffer
;
535 LPSTR pChar
= (LPSTR
)MmGetSystemAddressForMdl(Irp
->MdlAddress
);
540 vidmem
= DeviceExtension
->VideoMemory
;
541 offset
= (Buf
->dwCoord
.Y
* DeviceExtension
->Columns
* 2) +
542 (Buf
->dwCoord
.X
* 2);
544 for (dwCount
= 0; dwCount
< stk
->Parameters
.DeviceIoControl
.OutputBufferLength
; dwCount
++, pChar
++)
546 *pChar
= vidmem
[offset
+ (dwCount
* 2)];
549 Buf
->dwTransfered
= dwCount
;
551 Irp
->IoStatus
.Information
= sizeof(OUTPUT_ATTRIBUTE
);
552 Status
= STATUS_SUCCESS
;
556 case IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER
:
563 pCoord
= (COORD
*)MmGetSystemAddressForMdl(Irp
->MdlAddress
);
564 pChar
= (CHAR
*)(pCoord
+ 1);
565 vidmem
= DeviceExtension
->VideoMemory
;
566 offset
= (pCoord
->Y
* DeviceExtension
->Columns
* 2) +
569 for (dwCount
= 0; dwCount
< (stk
->Parameters
.DeviceIoControl
.InputBufferLength
- sizeof( COORD
)); dwCount
++, pChar
++)
571 vidmem
[offset
+ (dwCount
* 2)] = *pChar
;
574 Irp
->IoStatus
.Information
= 0;
575 Status
= STATUS_SUCCESS
;
581 Status
= STATUS_NOT_IMPLEMENTED
;
584 Irp
->IoStatus
.Status
= Status
;
585 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);
592 ScrDispatch(PDEVICE_OBJECT DeviceObject
,
595 PIO_STACK_LOCATION stk
= IoGetCurrentIrpStackLocation(Irp
);
598 switch (stk
->MajorFunction
)
601 Status
= STATUS_SUCCESS
;
605 Status
= STATUS_NOT_IMPLEMENTED
;
610 Irp
->IoStatus
.Status
= Status
;
611 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);
621 DriverEntry (PDRIVER_OBJECT DriverObject
, PUNICODE_STRING RegistryPath
)
623 PDEVICE_OBJECT DeviceObject
;
624 UNICODE_STRING DeviceName
= UNICODE_STRING_INITIALIZER(L
"\\Device\\BlueScreen");
625 UNICODE_STRING SymlinkName
= UNICODE_STRING_INITIALIZER(L
"\\??\\BlueScreen");
627 DPRINT ("Screen Driver 0.0.6\n");
629 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = (PDRIVER_DISPATCH
) ScrCreate
;
630 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = (PDRIVER_DISPATCH
) ScrDispatch
;
631 DriverObject
->MajorFunction
[IRP_MJ_READ
] = (PDRIVER_DISPATCH
) ScrDispatch
;
632 DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = (PDRIVER_DISPATCH
) ScrWrite
;
633 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = (PDRIVER_DISPATCH
) ScrIoControl
;
635 IoCreateDevice (DriverObject
,
636 sizeof(DEVICE_EXTENSION
),
643 IoCreateSymbolicLink (&SymlinkName
, &DeviceName
);
645 return (STATUS_SUCCESS
);