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);