\r processing.
[reactos.git] / reactos / drivers / dd / blue / blue.c
index 3b8e042..f951a09 100644 (file)
@@ -1,33 +1,45 @@
+/* $Id: blue.c,v 1.30 2001/07/30 11:49:38 ea Exp $
+ *
+ * COPYRIGHT:            See COPYING in the top level directory
+ * PROJECT:              ReactOS kernel
+ * FILE:                 services/dd/blue/blue.c
+ * PURPOSE:              Console (blue screen) device driver
+ * PROGRAMMER:           Eric Kohl (ekohl@abo.rhein-zeitung.de)
+ * UPDATE HISTORY:
+ *                       ??? Created
+ */
+
+/* INCLUDES ******************************************************************/
 
-#include <internal/mmhal.h>
-#include <internal/halio.h>
-#include <internal/hal/page.h>
 #include <ddk/ntddk.h>
+#include <ddk/ntddblue.h>
 #include <string.h>
-#include <internal/string.h>
 #include <defines.h>
-#include <ddk/ntddblue.h>
 
-//#define NDEBUG
-#include <internal/debug.h>
+#define NDEBUG
+#include <debug.h>
 
 
+/* DEFINITIONS ***************************************************************/
 
 #define VIDMEM_BASE        0xb8000
+#define VIDMEM_SIZE        0x2000
 
-#define NR_ROWS            50
-#define NR_COLUMNS         80
-
-#define CRTC_COMMAND       0x3d4
-#define CRTC_DATA          0x3d5
+#define CRTC_COMMAND       ((PUCHAR)0x3d4)
+#define CRTC_DATA          ((PUCHAR)0x3d5)
 
+#define CRTC_COLUMNS       0x01
+#define CRTC_OVERFLOW      0x07
+#define CRTC_ROWS          0x12
+#define CRTC_SCANLINES     0x09
 #define CRTC_CURSORSTART   0x0a
 #define CRTC_CURSOREND     0x0b
-#define CRTC_CURSORPOSLO   0x0f
 #define CRTC_CURSORPOSHI   0x0e
+#define CRTC_CURSORPOSLO   0x0f
 
-
-
+#define ATTRC_WRITEREG     ((PUCHAR)0x3c0)
+#define ATTRC_READREG      ((PUCHAR)0x3c1)
+#define ATTRC_INPST1       ((PUCHAR)0x3da)
 
 #define TAB_WIDTH          8
 
 
 typedef struct _DEVICE_EXTENSION
 {
-    PBYTE VideoMemory;
-    SHORT CursorX;
-    SHORT CursorY;
+    PBYTE VideoMemory;    /* Pointer to video memory */
     DWORD CursorSize;
     BOOL  CursorVisible;
     WORD  CharAttribute;
     DWORD Mode;
     BYTE  ScanLines;      /* Height of a text line */
-
+    WORD  Rows;           /* Number of rows        */
+    WORD  Columns;        /* Number of columns     */
 } DEVICE_EXTENSION, *PDEVICE_EXTENSION;
 
 
-
-
-
 /* FUNCTIONS **************************************************************/
 
-
-NTSTATUS ScrCreate (PDEVICE_OBJECT DeviceObject, PIRP Irp)
+NTSTATUS
+STDCALL ScrCreate (PDEVICE_OBJECT DeviceObject, PIRP Irp)
 {
-//    PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation (Irp);
     PDEVICE_EXTENSION DeviceExtension;
+    PHYSICAL_ADDRESS BaseAddress;
     NTSTATUS Status;
     unsigned int offset;
+    BYTE data, value;
 
     DeviceExtension = DeviceObject->DeviceExtension;
 
-    /* initialize device extension */
     /* get pointer to video memory */
-    DeviceExtension->VideoMemory = (PBYTE)physical_to_linear (VIDMEM_BASE);
+    BaseAddress.QuadPart = VIDMEM_BASE;
+    DeviceExtension->VideoMemory =
+        (PBYTE)MmMapIoSpace (BaseAddress, VIDMEM_SIZE, FALSE);
 
-    /* get current output position */
+    /* disable interrupts */
     __asm__("cli\n\t");
-    outb_p (CRTC_COMMAND, CRTC_CURSORPOSLO);
-    offset = inb_p (CRTC_DATA);
-    outb_p (CRTC_COMMAND, CRTC_CURSORPOSHI);
-    offset += (inb_p (CRTC_DATA) << 8);
-    __asm__("sti\n\t");
 
-    DeviceExtension->CursorX = (SHORT)(offset % NR_COLUMNS);
-    DeviceExtension->CursorY = (SHORT)(offset / NR_COLUMNS);
-    DeviceExtension->CursorSize    = 5; /* FIXME: value correct?? */
-    DeviceExtension->CursorVisible = TRUE;
+    /* get current output position */
+    WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO);
+    offset = READ_PORT_UCHAR (CRTC_DATA);
+    WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI);
+    offset += (READ_PORT_UCHAR (CRTC_DATA) << 8);
+
+    /* switch blinking characters off */
+    READ_PORT_UCHAR (ATTRC_INPST1);
+    value = READ_PORT_UCHAR (ATTRC_WRITEREG);
+    WRITE_PORT_UCHAR (ATTRC_WRITEREG, 0x10);
+    data  = READ_PORT_UCHAR (ATTRC_READREG);
+    data  = data & ~0x08;
+    WRITE_PORT_UCHAR (ATTRC_WRITEREG, data);
+    WRITE_PORT_UCHAR (ATTRC_WRITEREG, value);
+    READ_PORT_UCHAR (ATTRC_INPST1);
+
+    /* read screen information from crt controller */
+    WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_COLUMNS);
+    DeviceExtension->Columns = READ_PORT_UCHAR (CRTC_DATA) + 1;
+    WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_ROWS);
+    DeviceExtension->Rows = READ_PORT_UCHAR (CRTC_DATA);
+    WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_OVERFLOW);
+    data = READ_PORT_UCHAR (CRTC_DATA);
+    DeviceExtension->Rows |= (((data & 0x02) << 7) | ((data & 0x40) << 3));
+    DeviceExtension->Rows++;
+    WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_SCANLINES);
+    DeviceExtension->ScanLines = (READ_PORT_UCHAR (CRTC_DATA) & 0x1F) + 1;
+
+    /* enable interrupts */
+    __asm__("sti\n\t");
 
+    /* calculate number of text rows */
+    DeviceExtension->Rows =
+        DeviceExtension->Rows / DeviceExtension->ScanLines;
+#ifdef BOCHS_30ROWS
+    DeviceExtension->Rows = 30;
+#endif
 
-    DeviceExtension->ScanLines = 8; /* FIXME: read it from CRTC */
+    DPRINT ("%d Columns  %d Rows %d Scanlines\n",
+            DeviceExtension->Columns,
+            DeviceExtension->Rows,
+            DeviceExtension->ScanLines);
 
+    DeviceExtension->CursorSize    = 5; /* FIXME: value correct?? */
+    DeviceExtension->CursorVisible = TRUE;
 
     /* more initialization */
     DeviceExtension->CharAttribute = 0x17;  /* light grey on blue */
     DeviceExtension->Mode = ENABLE_PROCESSED_OUTPUT |
                             ENABLE_WRAP_AT_EOL_OUTPUT;
 
-    /* FIXME: more initialization?? */
-
-
     /* show blinking cursor */
-    /* FIXME: calculate cursor size */
     __asm__("cli\n\t");
-    outb_p (CRTC_COMMAND, CRTC_CURSORSTART);
-    outb_p (CRTC_DATA, 0x47);
-    outb_p (CRTC_COMMAND, CRTC_CURSOREND);
-    outb_p (CRTC_DATA, 0x07);
+    WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORSTART);
+    WRITE_PORT_UCHAR (CRTC_DATA, (DeviceExtension->ScanLines - 1) & 0x1F);
+    WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSOREND);
+    data = READ_PORT_UCHAR (CRTC_DATA) & 0xE0;
+    WRITE_PORT_UCHAR (CRTC_DATA,
+                      data | ((DeviceExtension->ScanLines - 1) & 0x1F));
     __asm__("sti\n\t");
 
-
     Status = STATUS_SUCCESS;
+
     Irp->IoStatus.Status = Status;
     IoCompleteRequest (Irp, IO_NO_INCREMENT);
 
@@ -117,108 +156,124 @@ NTSTATUS ScrCreate (PDEVICE_OBJECT DeviceObject, PIRP Irp)
 }
 
 
-NTSTATUS ScrWrite (PDEVICE_OBJECT DeviceObject, PIRP Irp)
+NTSTATUS
+STDCALL ScrWrite (PDEVICE_OBJECT DeviceObject, PIRP Irp)
 {
     PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation (Irp);
-    PDEVICE_EXTENSION DeviceExtension;
+    PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
     NTSTATUS Status;
     char *pch = Irp->UserBuffer;
     char *vidmem;
     int i, j, offset;
     int cursorx, cursory;
+    int rows, columns;
+    int processed = DeviceExtension->Mode & ENABLE_PROCESSED_OUTPUT;
 
-    DeviceExtension = DeviceObject->DeviceExtension;
     vidmem  = DeviceExtension->VideoMemory;
-    cursorx = DeviceExtension->CursorX;
-    cursory = DeviceExtension->CursorY;
-
-    for (i = 0; i < stk->Parameters.Write.Length; i++, pch++)
-    {
-        switch (*pch)
-        {
-            case '\b':
-                if (cursorx > 0)
-                {
-                    cursorx--;
-                }
-                else if (cursory > 0)
-                {
-                    cursorx = NR_COLUMNS - 1;
-                    cursory--;
-                }   
-                break;
-
-            case '\n':
-                cursory++;
-                cursorx = 0;
-                break;
-
-            case '\r':
-                break;
-
-            case '\t':
-                offset = TAB_WIDTH - (cursorx % TAB_WIDTH);
-                for (j = 0; j < offset; j++)
-                {
-                    vidmem[(cursorx * 2) + (cursory * NR_COLUMNS * 2)] = ' ';
-                    cursorx++;
-/*
-                    if (cursorx >= NR_COLUMNS)
-                    {
-                        cursory++;
-                        cursorx = 0;
-                    }
-*/
-                }
-                break;
-       
-            default:
-                vidmem[(cursorx * 2) + (cursory * NR_COLUMNS * 2)] = *pch;
-                vidmem[(cursorx * 2) + (cursory * NR_COLUMNS * 2) + 1] = (char) DeviceExtension->CharAttribute;
-                cursorx++;
-                if (cursorx >= NR_COLUMNS)
-                {
-                    cursory++;
-                    cursorx = 0;
-                }
-        }
-   
-   
-        if (cursory >= NR_ROWS)
-        {
-            unsigned short *LinePtr;
-
-            memcpy (vidmem, 
-                    &vidmem[NR_COLUMNS * 2], 
-                    NR_COLUMNS * (NR_ROWS - 1) * 2);
-
-            LinePtr = (unsigned short *) &vidmem[NR_COLUMNS * (NR_ROWS - 1) * 2];
-
-            for (j = 0; j < NR_COLUMNS; j++)
-            {
-                LinePtr[j] = DeviceExtension->CharAttribute << 8;
-            }
-            cursory = NR_ROWS - 1;
-        }
+    rows = DeviceExtension->Rows;
+    columns = DeviceExtension->Columns;
+
+    WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI);
+    offset = READ_PORT_UCHAR (CRTC_DATA)<<8;
+    WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO);
+    offset += READ_PORT_UCHAR (CRTC_DATA);
+
+    cursory = offset / columns;
+    cursorx = offset % columns;
+    if( processed == 0 )
+       {
+         /* raw output mode */
+         memcpy( &vidmem[(cursorx * 2) + (cursory * columns * 2)], pch, stk->Parameters.Write.Length );
+         offset += (stk->Parameters.Write.Length / 2);
+       }
+    else {
+       for (i = 0; i < stk->Parameters.Write.Length; i++, pch++)
+         {
+            switch (*pch)
+               {
+               case '\b':
+                  if (cursorx > 0)
+                     {
+                        cursorx--;
+                     }
+                  else if (cursory > 0)
+                     {
+                        cursorx = columns - 1;
+                        cursory--;
+                     }
+                  vidmem[(cursorx * 2) + (cursory * columns * 2)] = ' ';
+                  vidmem[(cursorx * 2) + (cursory * columns * 2) + 1] = (char) DeviceExtension->CharAttribute;
+                  break;
+                  
+               case '\n':
+                  cursory++;
+                  cursorx = 0;
+                  break;
+                  
+               case '\r':
+                  cursorx = 0;
+                  break;
+                  
+               case '\t':
+                  offset = TAB_WIDTH - (cursorx % TAB_WIDTH);
+                  for (j = 0; j < offset; j++)
+                     {
+                        vidmem[(cursorx * 2) + (cursory * columns * 2)] = ' ';
+                        cursorx++;
+                        
+                        if (cursorx >= columns)
+                           {
+                              cursory++;
+                              cursorx = 0;
+                           }
+                     }
+                  break;
+                  
+               default:
+                  vidmem[(cursorx * 2) + (cursory * columns * 2)] = *pch;
+                  vidmem[(cursorx * 2) + (cursory * columns * 2) + 1] = (char) DeviceExtension->CharAttribute;
+                  cursorx++;
+                  if (cursorx >= columns)
+                     {
+                        cursory++;
+                        cursorx = 0;
+                     }
+                  break;
+               }
+            if (cursory >= rows)
+               {
+                  unsigned short *LinePtr;
+
+                  memcpy (vidmem,
+                          &vidmem[columns * 2],
+                          columns * (rows - 1) * 2);
+
+                  LinePtr = (unsigned short *) &vidmem[columns * (rows - 1) * 2];
+
+                  for (j = 0; j < columns; j++)
+                     {
+                        LinePtr[j] = DeviceExtension->CharAttribute << 8;
+                     }
+                  cursory = rows - 1;
+                  for (j = 0; j < columns; j++)
+                     {
+                        vidmem[(j * 2) + (cursory * columns * 2)] = ' ';
+                        vidmem[(j * 2) + (cursory * columns * 2) + 1] = (char)DeviceExtension->CharAttribute;
+                     }
+               }
+         }
+       
+       /* Set the cursor position */
+       offset = (cursory * columns) + cursorx;
     }
-
-
-    /* Set the cursor position */
-  
-    offset = (cursory * NR_COLUMNS) + cursorx;
-   
-    outb_p (CRTC_COMMAND, CRTC_CURSORPOSLO);
-    outb_p (CRTC_DATA, offset);
-    outb_p (CRTC_COMMAND, CRTC_CURSORPOSHI);
+    WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO);
+    WRITE_PORT_UCHAR (CRTC_DATA, offset);
+    WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI);
     offset >>= 8;
-    outb_p (CRTC_DATA, offset);
-
-    DeviceExtension->CursorX = cursorx;
-    DeviceExtension->CursorY = cursory;
-
+    WRITE_PORT_UCHAR (CRTC_DATA, offset);
 
     Status = STATUS_SUCCESS;
-   
+
     Irp->IoStatus.Status = Status;
     IoCompleteRequest (Irp, IO_NO_INCREMENT);
 
@@ -226,58 +281,65 @@ NTSTATUS ScrWrite (PDEVICE_OBJECT DeviceObject, PIRP Irp)
 }
 
 
-
-
-NTSTATUS ScrIoControl (PDEVICE_OBJECT DeviceObject, PIRP Irp)
+NTSTATUS
+STDCALL ScrIoControl (PDEVICE_OBJECT DeviceObject, PIRP Irp)
 {
     PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation (Irp);
     PDEVICE_EXTENSION DeviceExtension;
     NTSTATUS Status;
-
-
     DeviceExtension = DeviceObject->DeviceExtension;
-
     switch (stk->Parameters.DeviceIoControl.IoControlCode)
     {
         case IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO:
             {
                 PCONSOLE_SCREEN_BUFFER_INFO pcsbi = (PCONSOLE_SCREEN_BUFFER_INFO)Irp->AssociatedIrp.SystemBuffer;
+                int rows = DeviceExtension->Rows;
+                int columns = DeviceExtension->Columns;
                 unsigned int offset;
 
+                /* read cursor position from crtc */
                 __asm__("cli\n\t");
-                outb_p (CRTC_COMMAND, CRTC_CURSORPOSLO);
-                offset = inb_p (CRTC_DATA);
-                outb_p (CRTC_COMMAND, CRTC_CURSORPOSHI);
-                offset += (inb_p (CRTC_DATA) << 8);
+                WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO);
+                offset = READ_PORT_UCHAR (CRTC_DATA);
+                WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI);
+                offset += (READ_PORT_UCHAR (CRTC_DATA) << 8);
                 __asm__("sti\n\t");
 
-                pcsbi->dwCursorPosition.X = (SHORT)(offset % NR_COLUMNS);
-                pcsbi->dwCursorPosition.Y = (SHORT)(offset / NR_COLUMNS);
+                pcsbi->dwSize.X = columns;
+                pcsbi->dwSize.Y = rows;
 
-                pcsbi->dwSize.X = NR_ROWS;
-                pcsbi->dwSize.Y = NR_COLUMNS;
+                pcsbi->dwCursorPosition.X = (SHORT)(offset % columns);
+                pcsbi->dwCursorPosition.Y = (SHORT)(offset / columns);
+
+                pcsbi->wAttributes = DeviceExtension->CharAttribute;
+
+                pcsbi->srWindow.Left   = 0;
+                pcsbi->srWindow.Right  = columns - 1;
+                pcsbi->srWindow.Top    = 0;
+                pcsbi->srWindow.Bottom = rows - 1;
+
+                pcsbi->dwMaximumWindowSize.X = columns;
+                pcsbi->dwMaximumWindowSize.Y = rows;
 
                 Irp->IoStatus.Information = sizeof (CONSOLE_SCREEN_BUFFER_INFO);
                 Status = STATUS_SUCCESS;
             }
             break;
-           
+
         case IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO:
             {
                 PCONSOLE_SCREEN_BUFFER_INFO pcsbi = (PCONSOLE_SCREEN_BUFFER_INFO)Irp->AssociatedIrp.SystemBuffer;
                 unsigned int offset;
 
-                DeviceExtension->CursorX = pcsbi->dwCursorPosition.X;
-                DeviceExtension->CursorY = pcsbi->dwCursorPosition.Y;
-
-                offset = (pcsbi->dwCursorPosition.Y * NR_COLUMNS) +
+                DeviceExtension->CharAttribute = pcsbi->wAttributes;
+                offset = (pcsbi->dwCursorPosition.Y * DeviceExtension->Columns) +
                           pcsbi->dwCursorPosition.X;
 
                 __asm__("cli\n\t");
-                outb_p (CRTC_COMMAND, CRTC_CURSORPOSLO);
-                outb_p (CRTC_DATA, offset);
-                outb_p (CRTC_COMMAND, CRTC_CURSORPOSHI);
-                outb_p (CRTC_DATA, offset>>8);
+                WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO);
+                WRITE_PORT_UCHAR (CRTC_DATA, offset);
+                WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI);
+                WRITE_PORT_UCHAR (CRTC_DATA, offset>>8);
                 __asm__("sti\n\t");
 
                 Irp->IoStatus.Information = 0;
@@ -287,14 +349,12 @@ NTSTATUS ScrIoControl (PDEVICE_OBJECT DeviceObject, PIRP Irp)
 
         case IOCTL_CONSOLE_GET_CURSOR_INFO:
             {
-//               PCONSOLE_CURSOR_INFO pcci = (PCONSOLE_CURSOR_INFO)Irp->AssociatedIrp.SystemBuffer;
+                PCONSOLE_CURSOR_INFO pcci = (PCONSOLE_CURSOR_INFO)Irp->AssociatedIrp.SystemBuffer;
 
-//               DPRINT("GetConsoleCursorInfo: pcci=%p\n", pcci);
-//               DPRINT("GetConsoleCursorInfo\n");
-//               pcci->dwSize = 10;
-//               pcci->bVisible = FALSE;
+                pcci->dwSize = DeviceExtension->CursorSize;
+                pcci->bVisible = DeviceExtension->CursorVisible;
 
-                Irp->IoStatus.Information = 0;
+                Irp->IoStatus.Information = sizeof (CONSOLE_CURSOR_INFO);
                 Status = STATUS_SUCCESS;
             }
             break;
@@ -302,7 +362,7 @@ NTSTATUS ScrIoControl (PDEVICE_OBJECT DeviceObject, PIRP Irp)
         case IOCTL_CONSOLE_SET_CURSOR_INFO:
             {
                 PCONSOLE_CURSOR_INFO pcci = (PCONSOLE_CURSOR_INFO)Irp->AssociatedIrp.SystemBuffer;
-                BYTE data;
+                BYTE data, value;
                 DWORD size, height;
 
                 DeviceExtension->CursorSize = pcci->dwSize;
@@ -317,10 +377,12 @@ NTSTATUS ScrIoControl (PDEVICE_OBJECT DeviceObject, PIRP Irp)
                 data |= (BYTE)(height - size);
 
                 __asm__("cli\n\t");
-                outb_p (CRTC_COMMAND, CRTC_CURSORSTART);
-                outb_p (CRTC_DATA, data);
-                outb_p (CRTC_COMMAND, CRTC_CURSOREND);
-                outb_p (CRTC_DATA, height - 1);
+                WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORSTART);
+                WRITE_PORT_UCHAR (CRTC_DATA, data);
+                WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSOREND);
+                value = READ_PORT_UCHAR (CRTC_DATA) & 0xE0;
+                WRITE_PORT_UCHAR (CRTC_DATA, value | (height - 1));
+
                 __asm__("sti\n\t");
 
                 Irp->IoStatus.Information = 0;
@@ -328,39 +390,98 @@ NTSTATUS ScrIoControl (PDEVICE_OBJECT DeviceObject, PIRP Irp)
             }
             break;
 
+        case IOCTL_CONSOLE_GET_MODE:
+            {
+                PCONSOLE_MODE pcm = (PCONSOLE_MODE)Irp->AssociatedIrp.SystemBuffer;
+
+                pcm->dwMode = DeviceExtension->Mode;
+
+                Irp->IoStatus.Information = sizeof(CONSOLE_MODE);
+                Status = STATUS_SUCCESS;
+            }
+            break;
+
+        case IOCTL_CONSOLE_SET_MODE:
+            {
+                PCONSOLE_MODE pcm = (PCONSOLE_MODE)Irp->AssociatedIrp.SystemBuffer;
 
+                DeviceExtension->Mode = pcm->dwMode;
+
+                Irp->IoStatus.Information = 0;
+                Status = STATUS_SUCCESS;
+            }
+            break;
 
         case IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE:
             {
-                PFILL_OUTPUT_ATTRIBUTE Buf = (PFILL_OUTPUT_ATTRIBUTE)Irp->AssociatedIrp.SystemBuffer;
+                POUTPUT_ATTRIBUTE Buf = (POUTPUT_ATTRIBUTE)Irp->AssociatedIrp.SystemBuffer;
                 char *vidmem;
                 int offset;
                 DWORD dwCount;
 
                 vidmem = DeviceExtension->VideoMemory;
-                offset = (DeviceExtension->CursorY * NR_COLUMNS * 2) +
-                         (DeviceExtension->CursorX * 2) + 1;
-
-                CHECKPOINT
+                offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) +
+                         (Buf->dwCoord.X * 2) + 1;
 
                 for (dwCount = 0; dwCount < Buf->nLength; dwCount++)
                 {
                     vidmem[offset + (dwCount * 2)] = (char) Buf->wAttribute;
                 }
+
+                Buf->dwTransfered = Buf->nLength;
                 
                 Irp->IoStatus.Information = 0;
                 Status = STATUS_SUCCESS;
             }
             break;
 
-#if 0
         case IOCTL_CONSOLE_READ_OUTPUT_ATTRIBUTE:
+            {
+                POUTPUT_ATTRIBUTE Buf = (POUTPUT_ATTRIBUTE)Irp->AssociatedIrp.SystemBuffer;
+                PWORD pAttr = (PWORD)MmGetSystemAddressForMdl(Irp->MdlAddress);
+                char *vidmem;
+                int offset;
+                DWORD dwCount;
+
+                vidmem = DeviceExtension->VideoMemory;
+                offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) +
+                         (Buf->dwCoord.X * 2) + 1;
+
+                for (dwCount = 0; dwCount < stk->Parameters.Write.Length; dwCount++, pAttr++)
+                {
+                    (char) *pAttr = vidmem[offset + (dwCount * 2)];
+                }
+
+                Buf->dwTransfered = dwCount;
+
+                Irp->IoStatus.Information = sizeof(OUTPUT_ATTRIBUTE);
+                Status = STATUS_SUCCESS;
+            }
+            break;
+
         case IOCTL_CONSOLE_WRITE_OUTPUT_ATTRIBUTE:
+            {
+                COORD *pCoord = (COORD *)MmGetSystemAddressForMdl(Irp->MdlAddress);
+               CHAR *pAttr = (CHAR *)(pCoord + 1);
+                char *vidmem;
+                int offset;
+                DWORD dwCount;
+
+                vidmem = DeviceExtension->VideoMemory;
+                offset = (pCoord->Y * DeviceExtension->Columns * 2) +
+                         (pCoord->X * 2) + 1;
+
+                for (dwCount = 0; dwCount < (stk->Parameters.Write.Length - sizeof( COORD )); dwCount++, pAttr++)
+                {
+                    vidmem[offset + (dwCount * 2)] = *pAttr;
+                }
+                Irp->IoStatus.Information = 0;
+                Status = STATUS_SUCCESS;
+            }
             break;
-#endif
 
         case IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE:
-            DeviceExtension->CharAttribute = (WORD)Irp->AssociatedIrp.SystemBuffer;
+            DeviceExtension->CharAttribute = (WORD)*(PWORD)Irp->AssociatedIrp.SystemBuffer;
             Irp->IoStatus.Information = 0;
             Status = STATUS_SUCCESS;
             break;
@@ -368,14 +489,14 @@ NTSTATUS ScrIoControl (PDEVICE_OBJECT DeviceObject, PIRP Irp)
 
         case IOCTL_CONSOLE_FILL_OUTPUT_CHARACTER:
             {
-                PFILL_OUTPUT_CHARACTER Buf = (PFILL_OUTPUT_CHARACTER)Irp->AssociatedIrp.SystemBuffer;
+                POUTPUT_CHARACTER Buf = (POUTPUT_CHARACTER)Irp->AssociatedIrp.SystemBuffer;
                 char *vidmem;
                 int offset;
                 DWORD dwCount;
 
                 vidmem = DeviceExtension->VideoMemory;
-                offset = (DeviceExtension->CursorY * NR_COLUMNS * 2) +
-                         (DeviceExtension->CursorX * 2);
+                offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) +
+                         (Buf->dwCoord.X * 2);
 
                 CHECKPOINT
 
@@ -384,36 +505,74 @@ NTSTATUS ScrIoControl (PDEVICE_OBJECT DeviceObject, PIRP Irp)
                     vidmem[offset + (dwCount * 2)] = (char) Buf->cCharacter;
                 }
 
+                Buf->dwTransfered = Buf->nLength;
+
                 Irp->IoStatus.Information = 0;
                 Status = STATUS_SUCCESS;
             }
             break;
 
+        case IOCTL_CONSOLE_READ_OUTPUT_CHARACTER:
+            {
+                POUTPUT_CHARACTER Buf = (POUTPUT_CHARACTER)Irp->AssociatedIrp.SystemBuffer;
+                LPSTR pChar = (LPSTR)MmGetSystemAddressForMdl(Irp->MdlAddress);
+                char *vidmem;
+                int offset;
+                DWORD dwCount;
 
+                vidmem = DeviceExtension->VideoMemory;
+                offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) +
+                         (Buf->dwCoord.X * 2);
 
-        default:
-            Status = STATUS_NOT_IMPLEMENTED;
-    }
+                for (dwCount = 0; dwCount < stk->Parameters.Write.Length; dwCount++, pChar++)
+                {
+                    *pChar = vidmem[offset + (dwCount * 2)];
+                }
 
-    Irp->IoStatus.Status = Status;
-    IoCompleteRequest (Irp, IO_NO_INCREMENT);
+                Buf->dwTransfered = dwCount;
 
-    return (Status);
-}
+                Irp->IoStatus.Information = sizeof(OUTPUT_ATTRIBUTE);
+                Status = STATUS_SUCCESS;
+            }
+            break;
 
+        case IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER:
+            {
+               COORD *pCoord;
+                LPSTR pChar;
+                char *vidmem;
+                int offset;
+                DWORD dwCount;
+               pCoord = (COORD *)MmGetSystemAddressForMdl(Irp->MdlAddress);
+               pChar = (CHAR *)(pCoord + 1);
+                vidmem = DeviceExtension->VideoMemory;
+                offset = (pCoord->Y * DeviceExtension->Columns * 2) +
+                         (pCoord->X * 2);
 
+                for (dwCount = 0; dwCount < (stk->Parameters.Write.Length - sizeof( COORD )); dwCount++, pChar++)
+                {
+                    vidmem[offset + (dwCount * 2)] = *pChar;
+                }
 
+               Irp->IoStatus.Information = 0;
+                Status = STATUS_SUCCESS;
+            }
+            break;
 
 
+        default:
+            Status = STATUS_NOT_IMPLEMENTED;
+    }
 
-VOID ScrStartIo(PDEVICE_OBJECT DeviceObject, PIRP Irp)
-{
-//   PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
-    
+    Irp->IoStatus.Status = Status;
+    IoCompleteRequest (Irp, IO_NO_INCREMENT);
+
+    return (Status);
 }
 
 
-NTSTATUS ScrDispatch (PDEVICE_OBJECT DeviceObject, PIRP Irp)
+NTSTATUS
+STDCALL ScrDispatch (PDEVICE_OBJECT DeviceObject, PIRP Irp)
 {
     PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
     NTSTATUS Status;
@@ -440,38 +599,35 @@ NTSTATUS ScrDispatch (PDEVICE_OBJECT DeviceObject, PIRP Irp)
 /*
  * Module entry point
  */
-STDCALL NTSTATUS
+NTSTATUS
+STDCALL
 DriverEntry (PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
 {
     PDEVICE_OBJECT DeviceObject;
-    ANSI_STRING adevice_name;
-    UNICODE_STRING device_name;
-    ANSI_STRING asymlink_name;
-    UNICODE_STRING symlink_name;
-   
-    DbgPrint ("Screen Driver 0.0.5\n");
+    UNICODE_STRING DeviceName;
+    UNICODE_STRING SymlinkName;
+
+    DbgPrint ("Screen Driver 0.0.6\n");
 
     DriverObject->MajorFunction[IRP_MJ_CREATE] = ScrCreate;
     DriverObject->MajorFunction[IRP_MJ_CLOSE]  = ScrDispatch;
     DriverObject->MajorFunction[IRP_MJ_READ]   = ScrDispatch;
     DriverObject->MajorFunction[IRP_MJ_WRITE]  = ScrWrite;
     DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL ] = ScrIoControl;
-    DriverObject->DriverStartIo = ScrStartIo;
 
-    RtlInitAnsiString (&adevice_name, "\\Device\\BlueScreen");
-    RtlAnsiStringToUnicodeString (&device_name, &adevice_name, TRUE);
+    RtlInitUnicodeString (&DeviceName, L"\\Device\\BlueScreen");
     IoCreateDevice (DriverObject,
                     sizeof(DEVICE_EXTENSION),
-                    &device_name,
+                    &DeviceName,
                     FILE_DEVICE_SCREEN,
                     0,
                     TRUE,
                     &DeviceObject);
 
-    RtlInitAnsiString (&asymlink_name, "\\??\\BlueScreen");
-    RtlAnsiStringToUnicodeString (&symlink_name, &asymlink_name, TRUE);
-    IoCreateSymbolicLink (&symlink_name, &device_name);
+    RtlInitUnicodeString (&SymlinkName, L"\\??\\BlueScreen");
+    IoCreateSymbolicLink (&SymlinkName, &DeviceName);
 
     return (STATUS_SUCCESS);
 }
 
+/* EOF */