1 /* $Id: blue.c,v 1.37 2003/03/21 21:09:40 hbirr 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>
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
,
74 PDEVICE_EXTENSION DeviceExtension
;
75 PHYSICAL_ADDRESS BaseAddress
;
80 DeviceExtension
= DeviceObject
->DeviceExtension
;
82 /* get pointer to video memory */
83 BaseAddress
.QuadPart
= VIDMEM_BASE
;
84 DeviceExtension
->VideoMemory
=
85 (PBYTE
)MmMapIoSpace (BaseAddress
, VIDMEM_SIZE
, FALSE
);
87 /* disable interrupts */
90 /* get current output position */
91 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSLO
);
92 offset
= READ_PORT_UCHAR (CRTC_DATA
);
93 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSHI
);
94 offset
+= (READ_PORT_UCHAR (CRTC_DATA
) << 8);
96 /* switch blinking characters off */
97 READ_PORT_UCHAR (ATTRC_INPST1
);
98 value
= READ_PORT_UCHAR (ATTRC_WRITEREG
);
99 WRITE_PORT_UCHAR (ATTRC_WRITEREG
, 0x10);
100 data
= READ_PORT_UCHAR (ATTRC_READREG
);
102 WRITE_PORT_UCHAR (ATTRC_WRITEREG
, data
);
103 WRITE_PORT_UCHAR (ATTRC_WRITEREG
, value
);
104 READ_PORT_UCHAR (ATTRC_INPST1
);
106 /* read screen information from crt controller */
107 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_COLUMNS
);
108 DeviceExtension
->Columns
= READ_PORT_UCHAR (CRTC_DATA
) + 1;
109 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_ROWS
);
110 DeviceExtension
->Rows
= READ_PORT_UCHAR (CRTC_DATA
);
111 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_OVERFLOW
);
112 data
= READ_PORT_UCHAR (CRTC_DATA
);
113 DeviceExtension
->Rows
|= (((data
& 0x02) << 7) | ((data
& 0x40) << 3));
114 DeviceExtension
->Rows
++;
115 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_SCANLINES
);
116 DeviceExtension
->ScanLines
= (READ_PORT_UCHAR (CRTC_DATA
) & 0x1F) + 1;
118 /* enable interrupts */
121 /* calculate number of text rows */
122 DeviceExtension
->Rows
=
123 DeviceExtension
->Rows
/ DeviceExtension
->ScanLines
;
125 DeviceExtension
->Rows
= 30;
128 DPRINT ("%d Columns %d Rows %d Scanlines\n",
129 DeviceExtension
->Columns
,
130 DeviceExtension
->Rows
,
131 DeviceExtension
->ScanLines
);
133 DeviceExtension
->CursorSize
= 5; /* FIXME: value correct?? */
134 DeviceExtension
->CursorVisible
= TRUE
;
136 /* more initialization */
137 DeviceExtension
->CharAttribute
= 0x17; /* light grey on blue */
138 DeviceExtension
->Mode
= ENABLE_PROCESSED_OUTPUT
|
139 ENABLE_WRAP_AT_EOL_OUTPUT
;
141 /* show blinking cursor */
143 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORSTART
);
144 WRITE_PORT_UCHAR (CRTC_DATA
, (DeviceExtension
->ScanLines
- 1) & 0x1F);
145 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSOREND
);
146 data
= READ_PORT_UCHAR (CRTC_DATA
) & 0xE0;
147 WRITE_PORT_UCHAR (CRTC_DATA
,
148 data
| ((DeviceExtension
->ScanLines
- 1) & 0x1F));
151 Status
= STATUS_SUCCESS
;
153 Irp
->IoStatus
.Status
= Status
;
154 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);
161 ScrWrite(PDEVICE_OBJECT DeviceObject
,
164 PIO_STACK_LOCATION stk
= IoGetCurrentIrpStackLocation (Irp
);
165 PDEVICE_EXTENSION DeviceExtension
= DeviceObject
->DeviceExtension
;
167 char *pch
= Irp
->UserBuffer
;
170 int cursorx
, cursory
;
172 int processed
= DeviceExtension
->Mode
& ENABLE_PROCESSED_OUTPUT
;
174 vidmem
= DeviceExtension
->VideoMemory
;
175 rows
= DeviceExtension
->Rows
;
176 columns
= DeviceExtension
->Columns
;
179 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSHI
);
180 offset
= READ_PORT_UCHAR (CRTC_DATA
)<<8;
181 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSLO
);
182 offset
+= READ_PORT_UCHAR (CRTC_DATA
);
185 cursory
= offset
/ columns
;
186 cursorx
= offset
% columns
;
189 /* raw output mode */
190 memcpy( &vidmem
[(cursorx
* 2) + (cursory
* columns
* 2)], pch
, stk
->Parameters
.Write
.Length
);
191 offset
+= (stk
->Parameters
.Write
.Length
/ 2);
194 for (i
= 0; i
< stk
->Parameters
.Write
.Length
; i
++, pch
++)
203 else if (cursory
> 0)
205 cursorx
= columns
- 1;
208 vidmem
[(cursorx
* 2) + (cursory
* columns
* 2)] = ' ';
209 vidmem
[(cursorx
* 2) + (cursory
* columns
* 2) + 1] = (char) DeviceExtension
->CharAttribute
;
222 offset
= TAB_WIDTH
- (cursorx
% TAB_WIDTH
);
223 for (j
= 0; j
< offset
; j
++)
225 vidmem
[(cursorx
* 2) + (cursory
* columns
* 2)] = ' ';
228 if (cursorx
>= columns
)
237 vidmem
[(cursorx
* 2) + (cursory
* columns
* 2)] = *pch
;
238 vidmem
[(cursorx
* 2) + (cursory
* columns
* 2) + 1] = (char) DeviceExtension
->CharAttribute
;
240 if (cursorx
>= columns
)
249 unsigned short *LinePtr
;
252 &vidmem
[columns
* 2],
253 columns
* (rows
- 1) * 2);
255 LinePtr
= (unsigned short *) &vidmem
[columns
* (rows
- 1) * 2];
257 for (j
= 0; j
< columns
; j
++)
259 LinePtr
[j
] = DeviceExtension
->CharAttribute
<< 8;
262 for (j
= 0; j
< columns
; j
++)
264 vidmem
[(j
* 2) + (cursory
* columns
* 2)] = ' ';
265 vidmem
[(j
* 2) + (cursory
* columns
* 2) + 1] = (char)DeviceExtension
->CharAttribute
;
270 /* Set the cursor position */
271 offset
= (cursory
* columns
) + cursorx
;
274 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSLO
);
275 WRITE_PORT_UCHAR (CRTC_DATA
, offset
);
276 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSHI
);
278 WRITE_PORT_UCHAR (CRTC_DATA
, offset
);
281 Status
= STATUS_SUCCESS
;
283 Irp
->IoStatus
.Status
= Status
;
284 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);
291 ScrIoControl(PDEVICE_OBJECT DeviceObject
,
294 PIO_STACK_LOCATION stk
= IoGetCurrentIrpStackLocation (Irp
);
295 PDEVICE_EXTENSION DeviceExtension
;
297 DeviceExtension
= DeviceObject
->DeviceExtension
;
298 switch (stk
->Parameters
.DeviceIoControl
.IoControlCode
)
300 case IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO
:
302 PCONSOLE_SCREEN_BUFFER_INFO pcsbi
= (PCONSOLE_SCREEN_BUFFER_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
303 int rows
= DeviceExtension
->Rows
;
304 int columns
= DeviceExtension
->Columns
;
307 /* read cursor position from crtc */
309 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSLO
);
310 offset
= READ_PORT_UCHAR (CRTC_DATA
);
311 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSHI
);
312 offset
+= (READ_PORT_UCHAR (CRTC_DATA
) << 8);
315 pcsbi
->dwSize
.X
= columns
;
316 pcsbi
->dwSize
.Y
= rows
;
318 pcsbi
->dwCursorPosition
.X
= (SHORT
)(offset
% columns
);
319 pcsbi
->dwCursorPosition
.Y
= (SHORT
)(offset
/ columns
);
321 pcsbi
->wAttributes
= DeviceExtension
->CharAttribute
;
323 pcsbi
->srWindow
.Left
= 0;
324 pcsbi
->srWindow
.Right
= columns
- 1;
325 pcsbi
->srWindow
.Top
= 0;
326 pcsbi
->srWindow
.Bottom
= rows
- 1;
328 pcsbi
->dwMaximumWindowSize
.X
= columns
;
329 pcsbi
->dwMaximumWindowSize
.Y
= rows
;
331 Irp
->IoStatus
.Information
= sizeof (CONSOLE_SCREEN_BUFFER_INFO
);
332 Status
= STATUS_SUCCESS
;
336 case IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO
:
338 PCONSOLE_SCREEN_BUFFER_INFO pcsbi
= (PCONSOLE_SCREEN_BUFFER_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
341 DeviceExtension
->CharAttribute
= pcsbi
->wAttributes
;
342 offset
= (pcsbi
->dwCursorPosition
.Y
* DeviceExtension
->Columns
) +
343 pcsbi
->dwCursorPosition
.X
;
346 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSLO
);
347 WRITE_PORT_UCHAR (CRTC_DATA
, offset
);
348 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSHI
);
349 WRITE_PORT_UCHAR (CRTC_DATA
, offset
>>8);
352 Irp
->IoStatus
.Information
= 0;
353 Status
= STATUS_SUCCESS
;
357 case IOCTL_CONSOLE_GET_CURSOR_INFO
:
359 PCONSOLE_CURSOR_INFO pcci
= (PCONSOLE_CURSOR_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
361 pcci
->dwSize
= DeviceExtension
->CursorSize
;
362 pcci
->bVisible
= DeviceExtension
->CursorVisible
;
364 Irp
->IoStatus
.Information
= sizeof (CONSOLE_CURSOR_INFO
);
365 Status
= STATUS_SUCCESS
;
369 case IOCTL_CONSOLE_SET_CURSOR_INFO
:
371 PCONSOLE_CURSOR_INFO pcci
= (PCONSOLE_CURSOR_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
375 DeviceExtension
->CursorSize
= pcci
->dwSize
;
376 DeviceExtension
->CursorVisible
= pcci
->bVisible
;
377 height
= DeviceExtension
->ScanLines
;
378 data
= (pcci
->bVisible
) ? 0x40 : 0x20;
380 size
= (pcci
->dwSize
* height
) / 100;
384 data
|= (BYTE
)(height
- size
);
387 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORSTART
);
388 WRITE_PORT_UCHAR (CRTC_DATA
, data
);
389 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSOREND
);
390 value
= READ_PORT_UCHAR (CRTC_DATA
) & 0xE0;
391 WRITE_PORT_UCHAR (CRTC_DATA
, value
| (height
- 1));
395 Irp
->IoStatus
.Information
= 0;
396 Status
= STATUS_SUCCESS
;
400 case IOCTL_CONSOLE_GET_MODE
:
402 PCONSOLE_MODE pcm
= (PCONSOLE_MODE
)Irp
->AssociatedIrp
.SystemBuffer
;
404 pcm
->dwMode
= DeviceExtension
->Mode
;
406 Irp
->IoStatus
.Information
= sizeof(CONSOLE_MODE
);
407 Status
= STATUS_SUCCESS
;
411 case IOCTL_CONSOLE_SET_MODE
:
413 PCONSOLE_MODE pcm
= (PCONSOLE_MODE
)Irp
->AssociatedIrp
.SystemBuffer
;
415 DeviceExtension
->Mode
= pcm
->dwMode
;
417 Irp
->IoStatus
.Information
= 0;
418 Status
= STATUS_SUCCESS
;
422 case IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE
:
424 POUTPUT_ATTRIBUTE Buf
= (POUTPUT_ATTRIBUTE
)Irp
->AssociatedIrp
.SystemBuffer
;
429 vidmem
= DeviceExtension
->VideoMemory
;
430 offset
= (Buf
->dwCoord
.Y
* DeviceExtension
->Columns
* 2) +
431 (Buf
->dwCoord
.X
* 2) + 1;
433 for (dwCount
= 0; dwCount
< Buf
->nLength
; dwCount
++)
435 vidmem
[offset
+ (dwCount
* 2)] = (char) Buf
->wAttribute
;
438 Buf
->dwTransfered
= Buf
->nLength
;
440 Irp
->IoStatus
.Information
= 0;
441 Status
= STATUS_SUCCESS
;
445 case IOCTL_CONSOLE_READ_OUTPUT_ATTRIBUTE
:
447 POUTPUT_ATTRIBUTE Buf
= (POUTPUT_ATTRIBUTE
)Irp
->AssociatedIrp
.SystemBuffer
;
448 PWORD pAttr
= (PWORD
)MmGetSystemAddressForMdl(Irp
->MdlAddress
);
453 vidmem
= DeviceExtension
->VideoMemory
;
454 offset
= (Buf
->dwCoord
.Y
* DeviceExtension
->Columns
* 2) +
455 (Buf
->dwCoord
.X
* 2) + 1;
457 for (dwCount
= 0; dwCount
< stk
->Parameters
.DeviceIoControl
.OutputBufferLength
; dwCount
++, pAttr
++)
459 (char) *pAttr
= vidmem
[offset
+ (dwCount
* 2)];
462 Buf
->dwTransfered
= dwCount
;
464 Irp
->IoStatus
.Information
= sizeof(OUTPUT_ATTRIBUTE
);
465 Status
= STATUS_SUCCESS
;
469 case IOCTL_CONSOLE_WRITE_OUTPUT_ATTRIBUTE
:
471 COORD
*pCoord
= (COORD
*)MmGetSystemAddressForMdl(Irp
->MdlAddress
);
472 CHAR
*pAttr
= (CHAR
*)(pCoord
+ 1);
477 vidmem
= DeviceExtension
->VideoMemory
;
478 offset
= (pCoord
->Y
* DeviceExtension
->Columns
* 2) +
481 for (dwCount
= 0; dwCount
< (stk
->Parameters
.DeviceIoControl
.InputBufferLength
- sizeof( COORD
)); dwCount
++, pAttr
++)
483 vidmem
[offset
+ (dwCount
* 2)] = *pAttr
;
485 Irp
->IoStatus
.Information
= 0;
486 Status
= STATUS_SUCCESS
;
490 case IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE
:
491 DeviceExtension
->CharAttribute
= (WORD
)*(PWORD
)Irp
->AssociatedIrp
.SystemBuffer
;
492 Irp
->IoStatus
.Information
= 0;
493 Status
= STATUS_SUCCESS
;
497 case IOCTL_CONSOLE_FILL_OUTPUT_CHARACTER
:
499 POUTPUT_CHARACTER Buf
= (POUTPUT_CHARACTER
)Irp
->AssociatedIrp
.SystemBuffer
;
504 vidmem
= DeviceExtension
->VideoMemory
;
505 offset
= (Buf
->dwCoord
.Y
* DeviceExtension
->Columns
* 2) +
506 (Buf
->dwCoord
.X
* 2);
510 for (dwCount
= 0; dwCount
< Buf
->nLength
; dwCount
++)
512 vidmem
[offset
+ (dwCount
* 2)] = (char) Buf
->cCharacter
;
515 Buf
->dwTransfered
= Buf
->nLength
;
517 Irp
->IoStatus
.Information
= 0;
518 Status
= STATUS_SUCCESS
;
522 case IOCTL_CONSOLE_READ_OUTPUT_CHARACTER
:
524 POUTPUT_CHARACTER Buf
= (POUTPUT_CHARACTER
)Irp
->AssociatedIrp
.SystemBuffer
;
525 LPSTR pChar
= (LPSTR
)MmGetSystemAddressForMdl(Irp
->MdlAddress
);
530 vidmem
= DeviceExtension
->VideoMemory
;
531 offset
= (Buf
->dwCoord
.Y
* DeviceExtension
->Columns
* 2) +
532 (Buf
->dwCoord
.X
* 2);
534 for (dwCount
= 0; dwCount
< stk
->Parameters
.DeviceIoControl
.OutputBufferLength
; dwCount
++, pChar
++)
536 *pChar
= vidmem
[offset
+ (dwCount
* 2)];
539 Buf
->dwTransfered
= dwCount
;
541 Irp
->IoStatus
.Information
= sizeof(OUTPUT_ATTRIBUTE
);
542 Status
= STATUS_SUCCESS
;
546 case IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER
:
553 pCoord
= (COORD
*)MmGetSystemAddressForMdl(Irp
->MdlAddress
);
554 pChar
= (CHAR
*)(pCoord
+ 1);
555 vidmem
= DeviceExtension
->VideoMemory
;
556 offset
= (pCoord
->Y
* DeviceExtension
->Columns
* 2) +
559 for (dwCount
= 0; dwCount
< (stk
->Parameters
.DeviceIoControl
.InputBufferLength
- sizeof( COORD
)); dwCount
++, pChar
++)
561 vidmem
[offset
+ (dwCount
* 2)] = *pChar
;
564 Irp
->IoStatus
.Information
= 0;
565 Status
= STATUS_SUCCESS
;
571 Status
= STATUS_NOT_IMPLEMENTED
;
574 Irp
->IoStatus
.Status
= Status
;
575 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);
582 ScrDispatch(PDEVICE_OBJECT DeviceObject
,
585 PIO_STACK_LOCATION stk
= IoGetCurrentIrpStackLocation(Irp
);
588 switch (stk
->MajorFunction
)
591 Status
= STATUS_SUCCESS
;
595 Status
= STATUS_NOT_IMPLEMENTED
;
600 Irp
->IoStatus
.Status
= Status
;
601 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);
611 DriverEntry (PDRIVER_OBJECT DriverObject
, PUNICODE_STRING RegistryPath
)
613 PDEVICE_OBJECT DeviceObject
;
614 UNICODE_STRING DeviceName
= UNICODE_STRING_INITIALIZER(L
"\\Device\\BlueScreen");
615 UNICODE_STRING SymlinkName
= UNICODE_STRING_INITIALIZER(L
"\\??\\BlueScreen");
617 DPRINT ("Screen Driver 0.0.6\n");
619 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = ScrCreate
;
620 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = ScrDispatch
;
621 DriverObject
->MajorFunction
[IRP_MJ_READ
] = ScrDispatch
;
622 DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = ScrWrite
;
623 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = ScrIoControl
;
625 IoCreateDevice (DriverObject
,
626 sizeof(DEVICE_EXTENSION
),
633 IoCreateSymbolicLink (&SymlinkName
, &DeviceName
);
635 return (STATUS_SUCCESS
);