blue.c

来自「一个类似windows」· C语言 代码 · 共 693 行 · 第 1/2 页

C
693
字号
/* $Id: blue.c 21706 2006-04-22 14:01:25Z tretiakov $
 *
 * 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 <ntddk.h>
#include <windef.h>
#define WINBASEAPI
typedef struct _SECURITY_ATTRIBUTES SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES;

#include <wincon.h>
#include <blue/ntddblue.h>
#include <ndk/halfuncs.h>

#define NDEBUG
#include <debug.h>

/* DEFINITIONS ***************************************************************/

#define VIDMEM_BASE        0xb8000

#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_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


/* NOTES ******************************************************************/
/*
 *  [[character][attribute]][[character][attribute]]....
 */


/* TYPEDEFS ***************************************************************/

typedef struct _DEVICE_EXTENSION
{
    PUCHAR VideoMemory;    /* Pointer to video memory */
    ULONG CursorSize;
    INT  CursorVisible;
    USHORT  CharAttribute;
    ULONG Mode;
    UCHAR  ScanLines;      /* Height of a text line */
    USHORT  Rows;           /* Number of rows        */
    USHORT  Columns;        /* Number of columns     */
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;


/* FUNCTIONS **************************************************************/

NTSTATUS STDCALL
DriverEntry (PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);

static NTSTATUS STDCALL
ScrCreate(PDEVICE_OBJECT DeviceObject,
	  PIRP Irp)
{
    PDEVICE_EXTENSION DeviceExtension;
    PHYSICAL_ADDRESS BaseAddress;
    NTSTATUS Status;
    unsigned int offset;
    UCHAR data, value;

    DeviceExtension = DeviceObject->DeviceExtension;

    /* disable interrupts */
    _disable();

    /* 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 */
    _enable();

    /* calculate number of text rows */
    DeviceExtension->Rows =
        DeviceExtension->Rows / DeviceExtension->ScanLines;
#ifdef BOCHS_30ROWS
    DeviceExtension->Rows = 30;
#endif

    DPRINT ("%d Columns  %d Rows %d Scanlines\n",
            DeviceExtension->Columns,
            DeviceExtension->Rows,
            DeviceExtension->ScanLines);

    /* get pointer to video memory */
    BaseAddress.QuadPart = VIDMEM_BASE;
    DeviceExtension->VideoMemory =
        (PUCHAR)MmMapIoSpace (BaseAddress, DeviceExtension->Rows * DeviceExtension->Columns * 2, MmNonCached);

    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;

    /* show blinking cursor */
    _disable();
    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));
    _enable();

    Status = STATUS_SUCCESS;

    Irp->IoStatus.Status = Status;
    IoCompleteRequest (Irp, IO_NO_INCREMENT);

    return (Status);
}


static NTSTATUS STDCALL
ScrWrite(PDEVICE_OBJECT DeviceObject,
	 PIRP Irp)
{
    PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation (Irp);
    PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
    NTSTATUS Status;
    char *pch = Irp->UserBuffer;
    PUCHAR vidmem;
    unsigned int i;
    int j, offset;
    int cursorx, cursory;
    int rows, columns;
    int processed = DeviceExtension->Mode & ENABLE_PROCESSED_OUTPUT;

    if (HalQueryDisplayOwnership())
       {
	  /* Display is in graphics mode, we're not allowed to touch it */
	  Status = STATUS_SUCCESS;

	  Irp->IoStatus.Status = Status;
	  IoCompleteRequest (Irp, IO_NO_INCREMENT);

	  return Status;
       }

    vidmem  = DeviceExtension->VideoMemory;
    rows = DeviceExtension->Rows;
    columns = DeviceExtension->Columns;

    _disable();
    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);
    _enable();

    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;
    }
    _disable();
    WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO);
    WRITE_PORT_UCHAR (CRTC_DATA, offset);
    WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI);
    offset >>= 8;
    WRITE_PORT_UCHAR (CRTC_DATA, offset);
    _enable();

    Status = STATUS_SUCCESS;

    Irp->IoStatus.Status = Status;
    IoCompleteRequest (Irp, IO_NO_INCREMENT);

    return (Status);
}


static 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 */
          _disable();
          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);
          _enable();

          pcsbi->dwSize.X = columns;
          pcsbi->dwSize.Y = rows;

          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;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?