1 /* $Id: blue.c,v 1.19 2000/01/11 17:33:44 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>
22 /* DEFINITIONS ***************************************************************/
24 #define IDMAP_BASE 0xd0000000
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
, PIRP Irp
)
72 PDEVICE_EXTENSION DeviceExtension
;
77 DeviceExtension
= DeviceObject
->DeviceExtension
;
79 /* initialize device extension */
81 /* get pointer to video memory */
82 /* FIXME : use MmMapIoSpace() */
83 DeviceExtension
->VideoMemory
= (PBYTE
)(IDMAP_BASE
+ VIDMEM_BASE
);
85 /* disable interrupts */
88 /* get current output position */
89 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSLO
);
90 offset
= READ_PORT_UCHAR (CRTC_DATA
);
91 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSHI
);
92 offset
+= (READ_PORT_UCHAR (CRTC_DATA
) << 8);
94 /* switch blinking characters off */
95 READ_PORT_UCHAR (ATTRC_INPST1
);
96 value
= READ_PORT_UCHAR (ATTRC_WRITEREG
);
97 WRITE_PORT_UCHAR (ATTRC_WRITEREG
, 0x10);
98 data
= READ_PORT_UCHAR (ATTRC_READREG
);
100 WRITE_PORT_UCHAR (ATTRC_WRITEREG
, data
);
101 WRITE_PORT_UCHAR (ATTRC_WRITEREG
, value
);
102 READ_PORT_UCHAR (ATTRC_INPST1
);
104 /* read screen information from crt controller */
105 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_COLUMNS
);
106 DeviceExtension
->Columns
= READ_PORT_UCHAR (CRTC_DATA
) + 1;
107 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_ROWS
);
108 DeviceExtension
->Rows
= READ_PORT_UCHAR (CRTC_DATA
);
109 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_OVERFLOW
);
110 data
= READ_PORT_UCHAR (CRTC_DATA
);
111 DeviceExtension
->Rows
|= (((data
& 0x02) << 7) | ((data
& 0x40) << 3));
112 DeviceExtension
->Rows
++;
113 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_SCANLINES
);
114 DeviceExtension
->ScanLines
= (READ_PORT_UCHAR (CRTC_DATA
) & 0x1F) + 1;
116 /* enable interrupts */
119 /* calculate number of text rows */
120 DeviceExtension
->Rows
=
121 DeviceExtension
->Rows
/ DeviceExtension
->ScanLines
;
123 DPRINT ("%d Columns %d Rows %d Scanlines\n",
124 DeviceExtension
->Columns
,
125 DeviceExtension
->Rows
,
126 DeviceExtension
->ScanLines
);
128 DeviceExtension
->CursorSize
= 5; /* FIXME: value correct?? */
129 DeviceExtension
->CursorVisible
= TRUE
;
131 /* more initialization */
132 DeviceExtension
->CharAttribute
= 0x17; /* light grey on blue */
133 DeviceExtension
->Mode
= ENABLE_PROCESSED_OUTPUT
|
134 ENABLE_WRAP_AT_EOL_OUTPUT
;
136 /* show blinking cursor */
138 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORSTART
);
139 WRITE_PORT_UCHAR (CRTC_DATA
, (DeviceExtension
->ScanLines
- 1) & 0x1F);
140 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSOREND
);
141 data
= READ_PORT_UCHAR (CRTC_DATA
) & 0xE0;
142 WRITE_PORT_UCHAR (CRTC_DATA
,
143 data
| ((DeviceExtension
->ScanLines
- 1) & 0x1F));
146 Status
= STATUS_SUCCESS
;
148 Irp
->IoStatus
.Status
= Status
;
149 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);
156 ScrWrite (PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
158 PIO_STACK_LOCATION stk
= IoGetCurrentIrpStackLocation (Irp
);
159 PDEVICE_EXTENSION DeviceExtension
;
161 char *pch
= Irp
->UserBuffer
;
164 int cursorx
, cursory
;
167 DeviceExtension
= DeviceObject
->DeviceExtension
;
168 vidmem
= DeviceExtension
->VideoMemory
;
169 rows
= DeviceExtension
->Rows
;
170 columns
= DeviceExtension
->Columns
;
172 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSHI
);
173 offset
= READ_PORT_UCHAR (CRTC_DATA
)<<8;
174 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSLO
);
175 offset
+= READ_PORT_UCHAR (CRTC_DATA
);
177 cursory
= offset
/ columns
;
178 cursorx
= offset
% columns
;
180 for (i
= 0; i
< stk
->Parameters
.Write
.Length
; i
++, pch
++)
189 else if (cursory
> 0)
191 cursorx
= columns
- 1;
205 offset
= TAB_WIDTH
- (cursorx
% TAB_WIDTH
);
206 for (j
= 0; j
< offset
; j
++)
208 vidmem
[(cursorx
* 2) + (cursory
* columns
* 2)] = ' ';
211 if (cursorx
>= columns
)
220 vidmem
[(cursorx
* 2) + (cursory
* columns
* 2)] = *pch
;
221 vidmem
[(cursorx
* 2) + (cursory
* columns
* 2) + 1] = (char) DeviceExtension
->CharAttribute
;
223 if (cursorx
>= columns
)
233 unsigned short *LinePtr
;
236 &vidmem
[columns
* 2],
237 columns
* (rows
- 1) * 2);
239 LinePtr
= (unsigned short *) &vidmem
[columns
* (rows
- 1) * 2];
241 for (j
= 0; j
< columns
; j
++)
243 LinePtr
[j
] = DeviceExtension
->CharAttribute
<< 8;
246 for (j
= 0; j
< columns
; j
++)
248 vidmem
[(j
* 2) + (cursory
* columns
* 2)] = ' ';
249 vidmem
[(j
* 2) + (cursory
* columns
* 2) + 1] = (char)DeviceExtension
->CharAttribute
;
254 /* Set the cursor position */
255 offset
= (cursory
* columns
) + cursorx
;
257 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSLO
);
258 WRITE_PORT_UCHAR (CRTC_DATA
, offset
);
259 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSHI
);
261 WRITE_PORT_UCHAR (CRTC_DATA
, offset
);
263 Status
= STATUS_SUCCESS
;
265 Irp
->IoStatus
.Status
= Status
;
266 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);
273 ScrIoControl (PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
275 PIO_STACK_LOCATION stk
= IoGetCurrentIrpStackLocation (Irp
);
276 PDEVICE_EXTENSION DeviceExtension
;
279 DeviceExtension
= DeviceObject
->DeviceExtension
;
281 switch (stk
->Parameters
.DeviceIoControl
.IoControlCode
)
283 case IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO
:
285 PCONSOLE_SCREEN_BUFFER_INFO pcsbi
= (PCONSOLE_SCREEN_BUFFER_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
286 int rows
= DeviceExtension
->Rows
;
287 int columns
= DeviceExtension
->Columns
;
290 /* read cursor position from crtc */
292 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSLO
);
293 offset
= READ_PORT_UCHAR (CRTC_DATA
);
294 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSHI
);
295 offset
+= (READ_PORT_UCHAR (CRTC_DATA
) << 8);
298 pcsbi
->dwSize
.X
= rows
;
299 pcsbi
->dwSize
.Y
= columns
;
301 pcsbi
->dwCursorPosition
.X
= (SHORT
)(offset
% columns
);
302 pcsbi
->dwCursorPosition
.Y
= (SHORT
)(offset
/ columns
);
304 pcsbi
->wAttributes
= DeviceExtension
->CharAttribute
;
306 pcsbi
->srWindow
.Left
= 0;
307 pcsbi
->srWindow
.Right
= columns
- 1;
308 pcsbi
->srWindow
.Top
= 0;
309 pcsbi
->srWindow
.Bottom
= rows
- 1;
311 pcsbi
->dwMaximumWindowSize
.X
= columns
;
312 pcsbi
->dwMaximumWindowSize
.Y
= rows
;
314 Irp
->IoStatus
.Information
= sizeof (CONSOLE_SCREEN_BUFFER_INFO
);
315 Status
= STATUS_SUCCESS
;
319 case IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO
:
321 PCONSOLE_SCREEN_BUFFER_INFO pcsbi
= (PCONSOLE_SCREEN_BUFFER_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
324 DeviceExtension
->CharAttribute
= pcsbi
->wAttributes
;
326 offset
= (pcsbi
->dwCursorPosition
.Y
* DeviceExtension
->Columns
) +
327 pcsbi
->dwCursorPosition
.X
;
330 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSLO
);
331 WRITE_PORT_UCHAR (CRTC_DATA
, offset
);
332 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSHI
);
333 WRITE_PORT_UCHAR (CRTC_DATA
, offset
>>8);
336 Irp
->IoStatus
.Information
= 0;
337 Status
= STATUS_SUCCESS
;
341 case IOCTL_CONSOLE_GET_CURSOR_INFO
:
343 PCONSOLE_CURSOR_INFO pcci
= (PCONSOLE_CURSOR_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
345 pcci
->dwSize
= DeviceExtension
->CursorSize
;
346 pcci
->bVisible
= DeviceExtension
->CursorVisible
;
348 Irp
->IoStatus
.Information
= sizeof (CONSOLE_CURSOR_INFO
);
349 Status
= STATUS_SUCCESS
;
353 case IOCTL_CONSOLE_SET_CURSOR_INFO
:
355 PCONSOLE_CURSOR_INFO pcci
= (PCONSOLE_CURSOR_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
359 DeviceExtension
->CursorSize
= pcci
->dwSize
;
360 DeviceExtension
->CursorVisible
= pcci
->bVisible
;
361 height
= DeviceExtension
->ScanLines
;
362 data
= (pcci
->bVisible
) ? 0x40 : 0x20;
364 size
= (pcci
->dwSize
* height
) / 100;
368 data
|= (BYTE
)(height
- size
);
371 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORSTART
);
372 WRITE_PORT_UCHAR (CRTC_DATA
, data
);
373 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSOREND
);
374 value
= READ_PORT_UCHAR (CRTC_DATA
) & 0xE0;
375 WRITE_PORT_UCHAR (CRTC_DATA
, value
| (height
- 1));
379 Irp
->IoStatus
.Information
= 0;
380 Status
= STATUS_SUCCESS
;
384 case IOCTL_CONSOLE_GET_MODE
:
386 PCONSOLE_MODE pcm
= (PCONSOLE_MODE
)Irp
->AssociatedIrp
.SystemBuffer
;
388 pcm
->dwMode
= DeviceExtension
->Mode
;
390 Irp
->IoStatus
.Information
= sizeof(CONSOLE_MODE
);
391 Status
= STATUS_SUCCESS
;
395 case IOCTL_CONSOLE_SET_MODE
:
397 PCONSOLE_MODE pcm
= (PCONSOLE_MODE
)Irp
->AssociatedIrp
.SystemBuffer
;
399 DeviceExtension
->Mode
= pcm
->dwMode
;
401 Irp
->IoStatus
.Information
= 0;
402 Status
= STATUS_SUCCESS
;
406 case IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE
:
408 POUTPUT_ATTRIBUTE Buf
= (POUTPUT_ATTRIBUTE
)Irp
->AssociatedIrp
.SystemBuffer
;
413 vidmem
= DeviceExtension
->VideoMemory
;
414 offset
= (Buf
->dwCoord
.Y
* DeviceExtension
->Columns
* 2) +
415 (Buf
->dwCoord
.X
* 2) + 1;
417 for (dwCount
= 0; dwCount
< Buf
->nLength
; dwCount
++)
419 vidmem
[offset
+ (dwCount
* 2)] = (char) Buf
->wAttribute
;
422 Buf
->dwTransfered
= Buf
->nLength
;
424 Irp
->IoStatus
.Information
= 0;
425 Status
= STATUS_SUCCESS
;
429 case IOCTL_CONSOLE_READ_OUTPUT_ATTRIBUTE
:
431 POUTPUT_ATTRIBUTE Buf
= (POUTPUT_ATTRIBUTE
)Irp
->AssociatedIrp
.SystemBuffer
;
432 LPWORD pAttr
= (LPWORD
)MmGetSystemAddressForMdl(Irp
->MdlAddress
);
437 vidmem
= DeviceExtension
->VideoMemory
;
438 offset
= (Buf
->dwCoord
.Y
* DeviceExtension
->Columns
* 2) +
439 (Buf
->dwCoord
.X
* 2) + 1;
441 for (dwCount
= 0; dwCount
< stk
->Parameters
.Write
.Length
; dwCount
++, pAttr
++)
443 (char) *pAttr
= vidmem
[offset
+ (dwCount
* 2)];
446 Buf
->dwTransfered
= dwCount
;
448 Irp
->IoStatus
.Information
= sizeof(OUTPUT_ATTRIBUTE
);
449 Status
= STATUS_SUCCESS
;
453 case IOCTL_CONSOLE_WRITE_OUTPUT_ATTRIBUTE
:
455 POUTPUT_ATTRIBUTE Buf
= (POUTPUT_ATTRIBUTE
)Irp
->AssociatedIrp
.SystemBuffer
;
456 LPWORD pAttr
= (LPWORD
)MmGetSystemAddressForMdl(Irp
->MdlAddress
);
461 vidmem
= DeviceExtension
->VideoMemory
;
462 offset
= (Buf
->dwCoord
.Y
* DeviceExtension
->Columns
* 2) +
463 (Buf
->dwCoord
.X
* 2) + 1;
465 for (dwCount
= 0; dwCount
< stk
->Parameters
.Write
.Length
; dwCount
++, pAttr
++)
467 vidmem
[offset
+ (dwCount
* 2)] = (char) *pAttr
;
470 Buf
->dwTransfered
= dwCount
;
472 Irp
->IoStatus
.Information
= sizeof(OUTPUT_ATTRIBUTE
);
473 Status
= STATUS_SUCCESS
;
477 case IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE
:
478 DeviceExtension
->CharAttribute
= (WORD
)*(LPWORD
)Irp
->AssociatedIrp
.SystemBuffer
;
479 Irp
->IoStatus
.Information
= 0;
480 Status
= STATUS_SUCCESS
;
484 case IOCTL_CONSOLE_FILL_OUTPUT_CHARACTER
:
486 POUTPUT_CHARACTER Buf
= (POUTPUT_CHARACTER
)Irp
->AssociatedIrp
.SystemBuffer
;
491 vidmem
= DeviceExtension
->VideoMemory
;
492 offset
= (Buf
->dwCoord
.Y
* DeviceExtension
->Columns
* 2) +
493 (Buf
->dwCoord
.X
* 2);
497 for (dwCount
= 0; dwCount
< Buf
->nLength
; dwCount
++)
499 vidmem
[offset
+ (dwCount
* 2)] = (char) Buf
->cCharacter
;
502 Buf
->dwTransfered
= Buf
->nLength
;
504 Irp
->IoStatus
.Information
= 0;
505 Status
= STATUS_SUCCESS
;
509 case IOCTL_CONSOLE_READ_OUTPUT_CHARACTER
:
511 POUTPUT_CHARACTER Buf
= (POUTPUT_CHARACTER
)Irp
->AssociatedIrp
.SystemBuffer
;
512 LPSTR pChar
= (LPSTR
)MmGetSystemAddressForMdl(Irp
->MdlAddress
);
517 vidmem
= DeviceExtension
->VideoMemory
;
518 offset
= (Buf
->dwCoord
.Y
* DeviceExtension
->Columns
* 2) +
519 (Buf
->dwCoord
.X
* 2);
521 for (dwCount
= 0; dwCount
< stk
->Parameters
.Write
.Length
; dwCount
++, pChar
++)
523 *pChar
= vidmem
[offset
+ (dwCount
* 2)];
526 Buf
->dwTransfered
= dwCount
;
528 Irp
->IoStatus
.Information
= sizeof(OUTPUT_ATTRIBUTE
);
529 Status
= STATUS_SUCCESS
;
533 case IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER
:
535 POUTPUT_CHARACTER Buf
= (POUTPUT_CHARACTER
)Irp
->AssociatedIrp
.SystemBuffer
;
536 LPSTR pChar
= (LPSTR
)MmGetSystemAddressForMdl(Irp
->MdlAddress
);
541 vidmem
= DeviceExtension
->VideoMemory
;
542 offset
= (Buf
->dwCoord
.Y
* DeviceExtension
->Columns
* 2) +
543 (Buf
->dwCoord
.X
* 2) + 1;
545 for (dwCount
= 0; dwCount
< stk
->Parameters
.Write
.Length
; dwCount
++, pChar
++)
547 vidmem
[offset
+ (dwCount
* 2)] = (char) *pChar
;
550 Buf
->dwTransfered
= dwCount
;
552 Irp
->IoStatus
.Information
= sizeof(OUTPUT_ATTRIBUTE
);
553 Status
= STATUS_SUCCESS
;
559 Status
= STATUS_NOT_IMPLEMENTED
;
562 Irp
->IoStatus
.Status
= Status
;
563 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);
570 ScrDispatch (PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
572 PIO_STACK_LOCATION stk
= IoGetCurrentIrpStackLocation(Irp
);
575 switch (stk
->MajorFunction
)
578 Status
= STATUS_SUCCESS
;
582 Status
= STATUS_NOT_IMPLEMENTED
;
587 Irp
->IoStatus
.Status
= Status
;
588 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);
598 DriverEntry (PDRIVER_OBJECT DriverObject
, PUNICODE_STRING RegistryPath
)
600 PDEVICE_OBJECT DeviceObject
;
601 ANSI_STRING adevice_name
;
602 UNICODE_STRING device_name
;
603 ANSI_STRING asymlink_name
;
604 UNICODE_STRING symlink_name
;
606 DbgPrint ("Screen Driver 0.0.6\n");
608 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = ScrCreate
;
609 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = ScrDispatch
;
610 DriverObject
->MajorFunction
[IRP_MJ_READ
] = ScrDispatch
;
611 DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = ScrWrite
;
612 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = ScrIoControl
;
614 RtlInitAnsiString (&adevice_name
, "\\Device\\BlueScreen");
615 RtlAnsiStringToUnicodeString (&device_name
, &adevice_name
, TRUE
);
616 IoCreateDevice (DriverObject
,
617 sizeof(DEVICE_EXTENSION
),
624 RtlInitAnsiString (&asymlink_name
, "\\??\\BlueScreen");
625 RtlAnsiStringToUnicodeString (&symlink_name
, &asymlink_name
, TRUE
);
626 IoCreateSymbolicLink (&symlink_name
, &device_name
);
628 RtlFreeUnicodeString (&device_name
);
629 RtlFreeUnicodeString (&symlink_name
);
631 return (STATUS_SUCCESS
);