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;
178 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI);
179 offset = READ_PORT_UCHAR (CRTC_DATA)<<8;
180 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO);
181 offset += READ_PORT_UCHAR (CRTC_DATA);
183 cursory = offset / columns;
184 cursorx = offset % columns;
187 /* raw output mode */
188 memcpy( &vidmem[(cursorx * 2) + (cursory * columns * 2)], pch, stk->Parameters.Write.Length );
189 offset += (stk->Parameters.Write.Length / 2);
192 for (i = 0; i < stk->Parameters.Write.Length; i++, pch++)
201 else if (cursory > 0)
203 cursorx = columns - 1;
206 vidmem[(cursorx * 2) + (cursory * columns * 2)] = ' ';
207 vidmem[(cursorx * 2) + (cursory * columns * 2) + 1] = (char) DeviceExtension->CharAttribute;
220 offset = TAB_WIDTH - (cursorx % TAB_WIDTH);
221 for (j = 0; j < offset; j++)
223 vidmem[(cursorx * 2) + (cursory * columns * 2)] = ' ';
226 if (cursorx >= columns)
235 vidmem[(cursorx * 2) + (cursory * columns * 2)] = *pch;
236 vidmem[(cursorx * 2) + (cursory * columns * 2) + 1] = (char) DeviceExtension->CharAttribute;
238 if (cursorx >= columns)
247 unsigned short *LinePtr;
250 &vidmem[columns * 2],
251 columns * (rows - 1) * 2);
253 LinePtr = (unsigned short *) &vidmem[columns * (rows - 1) * 2];
255 for (j = 0; j < columns; j++)
257 LinePtr[j] = DeviceExtension->CharAttribute << 8;
260 for (j = 0; j < columns; j++)
262 vidmem[(j * 2) + (cursory * columns * 2)] = ' ';
263 vidmem[(j * 2) + (cursory * columns * 2) + 1] = (char)DeviceExtension->CharAttribute;
268 /* Set the cursor position */
269 offset = (cursory * columns) + cursorx;
271 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO);
272 WRITE_PORT_UCHAR (CRTC_DATA, offset);
273 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI);
275 WRITE_PORT_UCHAR (CRTC_DATA, offset);
277 Status = STATUS_SUCCESS;
279 Irp->IoStatus.Status = Status;
280 IoCompleteRequest (Irp, IO_NO_INCREMENT);
287 ScrIoControl(PDEVICE_OBJECT DeviceObject,
290 PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation (Irp);
291 PDEVICE_EXTENSION DeviceExtension;
293 DeviceExtension = DeviceObject->DeviceExtension;
294 switch (stk->Parameters.DeviceIoControl.IoControlCode)
296 case IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO:
298 PCONSOLE_SCREEN_BUFFER_INFO pcsbi = (PCONSOLE_SCREEN_BUFFER_INFO)Irp->AssociatedIrp.SystemBuffer;
299 int rows = DeviceExtension->Rows;
300 int columns = DeviceExtension->Columns;
303 /* read cursor position from crtc */
305 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO);
306 offset = READ_PORT_UCHAR (CRTC_DATA);
307 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI);
308 offset += (READ_PORT_UCHAR (CRTC_DATA) << 8);
311 pcsbi->dwSize.X = columns;
312 pcsbi->dwSize.Y = rows;
314 pcsbi->dwCursorPosition.X = (SHORT)(offset % columns);
315 pcsbi->dwCursorPosition.Y = (SHORT)(offset / columns);
317 pcsbi->wAttributes = DeviceExtension->CharAttribute;
319 pcsbi->srWindow.Left = 0;
320 pcsbi->srWindow.Right = columns - 1;
321 pcsbi->srWindow.Top = 0;
322 pcsbi->srWindow.Bottom = rows - 1;
324 pcsbi->dwMaximumWindowSize.X = columns;
325 pcsbi->dwMaximumWindowSize.Y = rows;
327 Irp->IoStatus.Information = sizeof (CONSOLE_SCREEN_BUFFER_INFO);
328 Status = STATUS_SUCCESS;
332 case IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO:
334 PCONSOLE_SCREEN_BUFFER_INFO pcsbi = (PCONSOLE_SCREEN_BUFFER_INFO)Irp->AssociatedIrp.SystemBuffer;
337 DeviceExtension->CharAttribute = pcsbi->wAttributes;
338 offset = (pcsbi->dwCursorPosition.Y * DeviceExtension->Columns) +
339 pcsbi->dwCursorPosition.X;
342 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO);
343 WRITE_PORT_UCHAR (CRTC_DATA, offset);
344 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI);
345 WRITE_PORT_UCHAR (CRTC_DATA, offset>>8);
348 Irp->IoStatus.Information = 0;
349 Status = STATUS_SUCCESS;
353 case IOCTL_CONSOLE_GET_CURSOR_INFO:
355 PCONSOLE_CURSOR_INFO pcci = (PCONSOLE_CURSOR_INFO)Irp->AssociatedIrp.SystemBuffer;
357 pcci->dwSize = DeviceExtension->CursorSize;
358 pcci->bVisible = DeviceExtension->CursorVisible;
360 Irp->IoStatus.Information = sizeof (CONSOLE_CURSOR_INFO);
361 Status = STATUS_SUCCESS;
365 case IOCTL_CONSOLE_SET_CURSOR_INFO:
367 PCONSOLE_CURSOR_INFO pcci = (PCONSOLE_CURSOR_INFO)Irp->AssociatedIrp.SystemBuffer;
371 DeviceExtension->CursorSize = pcci->dwSize;
372 DeviceExtension->CursorVisible = pcci->bVisible;
373 height = DeviceExtension->ScanLines;
374 data = (pcci->bVisible) ? 0x40 : 0x20;
376 size = (pcci->dwSize * height) / 100;
380 data |= (BYTE)(height - size);
383 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORSTART);
384 WRITE_PORT_UCHAR (CRTC_DATA, data);
385 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSOREND);
386 value = READ_PORT_UCHAR (CRTC_DATA) & 0xE0;
387 WRITE_PORT_UCHAR (CRTC_DATA, value | (height - 1));
391 Irp->IoStatus.Information = 0;
392 Status = STATUS_SUCCESS;
396 case IOCTL_CONSOLE_GET_MODE:
398 PCONSOLE_MODE pcm = (PCONSOLE_MODE)Irp->AssociatedIrp.SystemBuffer;
400 pcm->dwMode = DeviceExtension->Mode;
402 Irp->IoStatus.Information = sizeof(CONSOLE_MODE);
403 Status = STATUS_SUCCESS;
407 case IOCTL_CONSOLE_SET_MODE:
409 PCONSOLE_MODE pcm = (PCONSOLE_MODE)Irp->AssociatedIrp.SystemBuffer;
411 DeviceExtension->Mode = pcm->dwMode;
413 Irp->IoStatus.Information = 0;
414 Status = STATUS_SUCCESS;
418 case IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE:
420 POUTPUT_ATTRIBUTE Buf = (POUTPUT_ATTRIBUTE)Irp->AssociatedIrp.SystemBuffer;
425 vidmem = DeviceExtension->VideoMemory;
426 offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) +
427 (Buf->dwCoord.X * 2) + 1;
429 for (dwCount = 0; dwCount < Buf->nLength; dwCount++)
431 vidmem[offset + (dwCount * 2)] = (char) Buf->wAttribute;
434 Buf->dwTransfered = Buf->nLength;
436 Irp->IoStatus.Information = 0;
437 Status = STATUS_SUCCESS;
441 case IOCTL_CONSOLE_READ_OUTPUT_ATTRIBUTE:
443 POUTPUT_ATTRIBUTE Buf = (POUTPUT_ATTRIBUTE)Irp->AssociatedIrp.SystemBuffer;
444 PWORD pAttr = (PWORD)MmGetSystemAddressForMdl(Irp->MdlAddress);
449 vidmem = DeviceExtension->VideoMemory;
450 offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) +
451 (Buf->dwCoord.X * 2) + 1;
453 for (dwCount = 0; dwCount < stk->Parameters.Write.Length; dwCount++, pAttr++)
455 (char) *pAttr = vidmem[offset + (dwCount * 2)];
458 Buf->dwTransfered = dwCount;
460 Irp->IoStatus.Information = sizeof(OUTPUT_ATTRIBUTE);
461 Status = STATUS_SUCCESS;
465 case IOCTL_CONSOLE_WRITE_OUTPUT_ATTRIBUTE:
467 COORD *pCoord = (COORD *)MmGetSystemAddressForMdl(Irp->MdlAddress);
468 CHAR *pAttr = (CHAR *)(pCoord + 1);
473 vidmem = DeviceExtension->VideoMemory;
474 offset = (pCoord->Y * DeviceExtension->Columns * 2) +
477 for (dwCount = 0; dwCount < (stk->Parameters.Write.Length - sizeof( COORD )); dwCount++, pAttr++)
479 vidmem[offset + (dwCount * 2)] = *pAttr;
481 Irp->IoStatus.Information = 0;
482 Status = STATUS_SUCCESS;
486 case IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE:
487 DeviceExtension->CharAttribute = (WORD)*(PWORD)Irp->AssociatedIrp.SystemBuffer;
488 Irp->IoStatus.Information = 0;
489 Status = STATUS_SUCCESS;
493 case IOCTL_CONSOLE_FILL_OUTPUT_CHARACTER:
495 POUTPUT_CHARACTER Buf = (POUTPUT_CHARACTER)Irp->AssociatedIrp.SystemBuffer;
500 vidmem = DeviceExtension->VideoMemory;
501 offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) +
502 (Buf->dwCoord.X * 2);
506 for (dwCount = 0; dwCount < Buf->nLength; dwCount++)
508 vidmem[offset + (dwCount * 2)] = (char) Buf->cCharacter;
511 Buf->dwTransfered = Buf->nLength;
513 Irp->IoStatus.Information = 0;
514 Status = STATUS_SUCCESS;
518 case IOCTL_CONSOLE_READ_OUTPUT_CHARACTER:
520 POUTPUT_CHARACTER Buf = (POUTPUT_CHARACTER)Irp->AssociatedIrp.SystemBuffer;
521 LPSTR pChar = (LPSTR)MmGetSystemAddressForMdl(Irp->MdlAddress);
526 vidmem = DeviceExtension->VideoMemory;
527 offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) +
528 (Buf->dwCoord.X * 2);
530 for (dwCount = 0; dwCount < stk->Parameters.Write.Length; dwCount++, pChar++)
532 *pChar = vidmem[offset + (dwCount * 2)];
535 Buf->dwTransfered = dwCount;
537 Irp->IoStatus.Information = sizeof(OUTPUT_ATTRIBUTE);
538 Status = STATUS_SUCCESS;
542 case IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER:
549 pCoord = (COORD *)MmGetSystemAddressForMdl(Irp->MdlAddress);
550 pChar = (CHAR *)(pCoord + 1);
551 vidmem = DeviceExtension->VideoMemory;
552 offset = (pCoord->Y * DeviceExtension->Columns * 2) +
555 for (dwCount = 0; dwCount < (stk->Parameters.Write.Length - sizeof( COORD )); dwCount++, pChar++)
557 vidmem[offset + (dwCount * 2)] = *pChar;
560 Irp->IoStatus.Information = 0;
561 Status = STATUS_SUCCESS;
567 Status = STATUS_NOT_IMPLEMENTED;
570 Irp->IoStatus.Status = Status;
571 IoCompleteRequest (Irp, IO_NO_INCREMENT);
578 ScrDispatch(PDEVICE_OBJECT DeviceObject,
581 PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
584 switch (stk->MajorFunction)
587 Status = STATUS_SUCCESS;
591 Status = STATUS_NOT_IMPLEMENTED;
596 Irp->IoStatus.Status = Status;
597 IoCompleteRequest (Irp, IO_NO_INCREMENT);
607 DriverEntry (PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
609 PDEVICE_OBJECT DeviceObject;
610 UNICODE_STRING DeviceName = UNICODE_STRING_INITIALIZER(L"\\Device\\BlueScreen");
611 UNICODE_STRING SymlinkName = UNICODE_STRING_INITIALIZER(L"\\??\\BlueScreen");
613 DPRINT ("Screen Driver 0.0.6\n");
615 DriverObject->MajorFunction[IRP_MJ_CREATE] = ScrCreate;
616 DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScrDispatch;
617 DriverObject->MajorFunction[IRP_MJ_READ] = ScrDispatch;
618 DriverObject->MajorFunction[IRP_MJ_WRITE] = ScrWrite;
619 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL ] = ScrIoControl;
621 IoCreateDevice (DriverObject,
622 sizeof(DEVICE_EXTENSION),
629 IoCreateSymbolicLink (&SymlinkName, &DeviceName);
631 return (STATUS_SUCCESS);