This repository has been archived on 2025-02-27. You can view files and clone it, but cannot push or open issues or pull requests.
CnC_Renegade/Code/Tools/MonoDrv/sys/monodrvr.c

1659 lines
71 KiB
C
Raw Permalink Normal View History

/*
** Command & Conquer Renegade(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* $Header$ */
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : NT Device Driver *
* *
* File Name : MONODRVR.C *
* *
* Programmer : Joe L. Bostic *
* *
* Start Date : 01/04/97 *
* *
* Last Update : January 6, 1997 [JLB] *
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* Display_Signon_Banner -- Display the signon banner at driver start. *
* DriverEntry -- Offical driver start entry point. *
* Mono_Bring_To_Top -- Brings the mono page to the visible top of the display stack. *
* Mono_Claim_Resources -- Claims resources for the MGA driver. *
* Mono_Clear_Screen -- Clears the monochrome screen & homes cursor. *
* Mono_Detect_MGA_Adapter -- Try to detec the MGA adapter. *
* Mono_Dispatch -- Main IRP dispatch handler routine. *
* Mono_Fetch_Ptr -- Fetch a USER address space pointer to mono buffer. *
* Mono_Fill_Attribute -- Fills rectangle with attribute specified. *
* Mono_Get_Address_Ptr -- Converts a physical address into a usable pointer. *
* Mono_Init_Buffer -- Initialize a mono buffer to known (unused) state. *
* Mono_Pan -- Pan the mono screen over one column. *
* Mono_Print -- Prints text (with formatting) to mono screen. *
* Mono_Print_Raw -- Print text (without processing) to mono screen. *
* Mono_Printf -- Print formatted text to the mono device. *
* Mono_Scroll -- Scroll the mono screen up one line. *
* Mono_Set_View_Pos -- Set the mono display ram view offset. *
* Mono_Unload -- Unloads the driver from the system. *
* Mono_Unreport_Resource_Usage -- Free reported hardware usage. *
* Mono_Update_Cursor -- Updates the CRTC cursor to reflect current visible page. *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "ntddk.h"
#include "stdarg.h"
#include "stdio.h"
#include "monodrvr.h"
/*
** Name constants.
*/
#define DEVICE_NAME L"\\Device\\Mono" // Unicode internal device name.
#define A_DEVICE_NAME "\\Device\\Mono" // ASCII internal device name.
#define SYMBOLIC_NAME L"\\DosDevices\\MONO" // Unicode symbolic name.
#define A_SYMBOLIC_NAME "\\DosDevices\\MONO" // ASCII symbolic name.
#define RESOURCE_NAME L"LOADED MONO DRIVER RESOURCES" // Hardware registry name.
/*
** MGA adapter hardware constants.
*/
#define CRTC_REGISTER 0x3B4 // CRTC port address.
#define CRTC_CONTROL 0x3B8 // CRTC control register address.
#define MONO_MEMORY 0xB0000 // MGA video ram physical address.
#define DEFAULT_ATTRIBUTE 0x07 // Normal character attribute (white on black).
/*
** Mono dimension constants.
*/
#define MONO_WIDTH 80 // Number of characters wide each page.
#define MONO_HEIGHT 25 // Number of lines tall each page.
#define MONO_MEM_LENGTH (0x10000-1) // Number of mono video RAM bytes.
#define MONO_PAGE_SIZE (MONO_WIDTH * MONO_HEIGHT * sizeof(unsigned short)) // Page size (bytes)
#define MONO_MAX_PAGES ((MONO_MEM_LENGTH+1) / MONO_PAGE_SIZE) // Number of mono pages in video RAM.
/*
** Helper pseudofunctions.
*/
#define BUILD_MONO_CHAR(c, a) ((unsigned short)(((a) << 8) | ((c) & 0xFF)))
#define PINDEX_TO_CELL(index) ((index) * MONO_WIDTH * MONO_HEIGHT)
#define ARRAY_SIZE(x) ((int)(sizeof(x)/sizeof(x[0])))
#define IS_FLAG_ON(x, flag) ((x->Flags & (1<<(flag))) != 0)
#define FLAG_SET(x, flag) x->Flags |= (1<<(flag))
#define FLAG_CLEAR(x, flag) x->Flags &= ~(1<<(flag))
/*
** This controls the state information for each of the
** display pages.
*/
typedef struct BuffControl
{
/*
** This is the cursor position within the current window
** on the mono buffer.
*/
int XPos;
int YPos;
/*
** This specifies the dimensions of the current window
** on the mono display.
*/
int WinX;
int WinY;
int WinW;
int WinH;
/*
** This is the default attribute to use when displaying text.
*/
int Attribute;
/*
** This is the logical address of the display page that this
** buffer represents. This pointer is in the address space
** of this driver, NOT of the owner of the file object. This
** pointer can and does change as the page stack changes.
*/
unsigned short * Buffer;
/*
** This is a copy of a pointer to the page memory that is
** in mapped to the owning file object's address space. If this
** pointer is not NULL, then the page is locked (see LockCount).
*/
void * LockPtr;
/*
** Records the number of times this mono page has been locked.
** If the page is locked, its position in the display stack cannot
** be changed.
*/
int LockCount;
/*
** If this page has been allocated, then this flag will
** be true.
*/
int Allocated;
/*
** These are the behavior flags for this buffer.
*/
long Flags;
} BuffControl;
/*
** This stores the global information for the monochrome driver.
*/
typedef struct MonoGlobals
{
/*
** Syncronizing object so that access to this device is
** serialized.
*/
KEVENT SyncEvent;
/*
** Logical pointer to the CRTC registers.
*/
unsigned char * CRTCRegisters;
/*
** Points to the first character of the MGA display
** memory.
*/
unsigned short * DisplayMemory;
/*
** Each of the display pages is managed by this buffer
** control array.
*/
BuffControl Control[MONO_MAX_PAGES];
/*
** This is the index of the currently visible display page. This
** means that the BuffControl indicated by this index has its
** Buffer pointer pointing to 0xB0000 physical memory.
*/
int CurrentVisible;
} MonoGlobals;
/*
** Describes an MGA resource needed for this driver.
*/
typedef struct MonoResourceType
{
unsigned long PhysicalAddress;
unsigned long Length;
unsigned long AddressSpace;
unsigned long RangeSharable;
} MonoResourceType;
/*
** List of MGA resources needed by this driver.
*/
MonoResourceType MonoResources[2] =
{
{MONO_MEMORY, MONO_MEM_LENGTH, 0, 1}, // MGA memory
{CRTC_REGISTER, 2, 1, 1} // CRTC register
#ifdef NEVER
,{CRTC_CONTROL, 1, 1, 1} // Mode control register.
#endif
};
/*
** This is the only public entry point for this driver.
*/
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);
/*
** Internal routines for the driver.
*/
static BOOLEAN Mono_Claim_Resources(PDRIVER_OBJECT DriverObject);
static BOOLEAN Mono_Detect_MGA_Adapter(void);
static NTSTATUS Mono_Dispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp);
static void Mono_Fill_Attribute(BuffControl * control, int x, int y, int w, int h, int attrib);
static void * Mono_Fetch_Ptr(MonoGlobals * device, BuffControl * page);
static void * Mono_Get_Address_Ptr(PHYSICAL_ADDRESS PhysicalAddress, unsigned long AddressSpace, unsigned long NumberOfBytes);
static void Display_Signon_Banner(BuffControl * control);
static void Mono_Bring_To_Top(MonoGlobals * device, BuffControl * page);
static void Mono_Clear_Screen(BuffControl * control);
static void Mono_Free_Resources(PDRIVER_OBJECT DriverObject);
static void Mono_Init_Buffer(BuffControl * buffer);
static void Mono_Pan(BuffControl * control);
static void Mono_Print(BuffControl * control, unsigned char * string, unsigned long length);
static void Mono_Print_Raw(BuffControl * control, unsigned char * string, unsigned long length);
static void Mono_Printf(BuffControl * control, char const * DbgMessage, ...);
static void Mono_Scroll(BuffControl * control);
static void Mono_Set_View_Pos(MonoGlobals * device, int pos);
static void Mono_Unload(PDRIVER_OBJECT driver);
static void Mono_Update_Cursor(MonoGlobals * device);
/***********************************************************************************************
* DriverEntry -- Offical driver start entry point. *
* *
* This routine is called by the system when the driver is first loaded. It is responsible *
* for initializing the driver state. *
* *
* INPUT: driverobject -- Pointer to the loaded driver object. *
* *
* registry -- Pointer to the registry string for this driver object. *
* *
* OUTPUT: Returns with the NTSTATUS of the driver initialization. If it is anything but *
* STATUS_SUCCESS, the the driver will not load. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 01/06/1997 JLB : Created. *
*=============================================================================================*/
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
NTSTATUS error_flag = STATUS_UNSUCCESSFUL;
/*
** Check the registry to see if the MGA resources are free to be claimed (claim them
** if they are) and also check that the MGA hardware is present. Only if both
** are true can the driver be loaded.
*/
if (Mono_Claim_Resources(DriverObject) && Mono_Detect_MGA_Adapter()) {
PDEVICE_OBJECT device_object = NULL;
UNICODE_STRING device_name;
/*
** Creates the device object.
*/
RtlInitUnicodeString(&device_name, DEVICE_NAME);
error_flag = IoCreateDevice(DriverObject, sizeof(MonoGlobals), &device_name, FILE_DEVICE_MONO, 0, FALSE, &device_object);
if (NT_SUCCESS(error_flag)) {
MonoGlobals * mono_globals = (MonoGlobals *)device_object->DeviceExtension;
/*
** This enables the WriteFile/ReadFile Win32 functions.
*/
device_object->Flags |= DO_BUFFERED_IO;
/*
** Initialize the dispatch event object. This allows us to
** synchronize access to the h/w registers...
*/
KeInitializeEvent(&mono_globals->SyncEvent, SynchronizationEvent, TRUE);
/*
** Map all the required resources, save the addresses
*/
mono_globals->DisplayMemory = Mono_Get_Address_Ptr(RtlConvertUlongToLargeInteger(MONO_MEMORY), 0, MONO_MEM_LENGTH);
mono_globals->CRTCRegisters = Mono_Get_Address_Ptr(RtlConvertUlongToLargeInteger(CRTC_REGISTER), 1, 2);
if (mono_globals->DisplayMemory != NULL && mono_globals->CRTCRegisters != NULL) {
UNICODE_STRING link_name;
/*
** Create a symbolic link that Win32 apps can specify to gain access
** to this driver/device
*/
RtlInitUnicodeString(&link_name, SYMBOLIC_NAME);
error_flag = IoCreateSymbolicLink(&link_name, &device_name);
if (NT_SUCCESS(error_flag)) {
int index;
/*
** Create dispatch points for device control, create, close.
*/
DriverObject->MajorFunction[IRP_MJ_CREATE] = Mono_Dispatch;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = Mono_Dispatch;
DriverObject->MajorFunction[IRP_MJ_READ] = Mono_Dispatch;
DriverObject->MajorFunction[IRP_MJ_WRITE] = Mono_Dispatch;
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = Mono_Dispatch;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = Mono_Dispatch;
DriverObject->DriverUnload = Mono_Unload;
/*
** Set the Start Address registers (indicate which part of
** video buffer is displayed) to 0
*/
Mono_Set_View_Pos(mono_globals, 0);
mono_globals->CurrentVisible = 0;
for (index = 0; index < MONO_MAX_PAGES; index++) {
mono_globals->Control[index].Buffer = &mono_globals->DisplayMemory[PINDEX_TO_CELL(index)];
Mono_Init_Buffer(&mono_globals->Control[index]);
}
/*
** Display the signon banner.
*/
Display_Signon_Banner(&mono_globals->Control[mono_globals->CurrentVisible]);
Mono_Update_Cursor(mono_globals);
}
} else {
error_flag = STATUS_UNSUCCESSFUL;
}
}
} else {
error_flag = STATUS_UNSUCCESSFUL;
}
/*
** If an error was detected during initialization, then unload the
** driver before returning the error flag to the system.
*/
if (!NT_SUCCESS(error_flag)) {
Mono_Unload(DriverObject);
}
return(error_flag);
}
/***********************************************************************************************
* Mono_Dispatch -- Main IRP dispatch handler routine. *
* *
* This routine is called whenever an IRP occurs. It is passed the driver object pointer *
* and the IRP info. *
* *
* INPUT: driver -- Pointer to the device object. *
* *
* irp -- Pointer to the IRP object. *
* *
* OUTPUT: Returns with the NTSTATUS of this IRP handler. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 01/06/1997 JLB : Created. *
*=============================================================================================*/
NTSTATUS Mono_Dispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
PIO_STACK_LOCATION irpStack;
MonoGlobals * mono_globals;
void * ioBuffer;
unsigned long inputBufferLength;
unsigned long outputBufferLength;
unsigned long ioControlCode;
NTSTATUS ntStatus;
FILE_OBJECT * fileobject = NULL;
BuffControl * control = NULL;
int currentindex = -1;
/*
** Presume success in the command processing.
*/
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0; // Bytes read/written or other return value.
/*
** Get a pointer to the current location in the Irp. This is where
** the function codes and parameters are located.
*/
irpStack = IoGetCurrentIrpStackLocation(Irp);
/*
** Get a pointer to the device extension
*/
mono_globals = DeviceObject->DeviceExtension;
/*
** Fetch the file object for this I/O request.
*/
fileobject = irpStack->FileObject;
if (fileobject != NULL) {
currentindex = (long)fileobject->FsContext;
}
/*
** Get the pointer to the input/output buffer and it's length
*/
ioBuffer = Irp->AssociatedIrp.SystemBuffer;
inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
/*
** Synchronize execution of the dispatch routine by acquiring the device
** event object. This ensures all request are serialized.
*/
KeWaitForSingleObject(&mono_globals->SyncEvent, Executive, KernelMode, FALSE, NULL);
/*
** Get a working pointer to the display page.
*/
if (currentindex == -1) {
currentindex == mono_globals->CurrentVisible;
}
control = &mono_globals->Control[currentindex];
switch (irpStack->MajorFunction) {
case IRP_MJ_READ:
break;
/*
** Process WriteFile request to display text.
*/
case IRP_MJ_WRITE:
if (ioBuffer != NULL && irpStack->Parameters.Write.Length > 0) {
Mono_Print(control, ioBuffer, irpStack->Parameters.Write.Length);
Irp->IoStatus.Information = irpStack->Parameters.Write.Length;
}
break;
/*
** The create event is called when a file object is first created. At that
** time, designate a context buffer and inialize it.
*/
case IRP_MJ_CREATE: {
int j;
int avail = -1;
/*
** Search for a free page to use.
*/
for (j = 0; j < MONO_MAX_PAGES; j++) {
if (!mono_globals->Control[j].Allocated) {
avail = j;
break;
}
}
/*
** If one is not found, then return with error.
*/
if (avail == -1) {
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
} else {
BuffControl * newcon = &mono_globals->Control[avail];
Mono_Init_Buffer(newcon);
newcon->Allocated = TRUE;
Mono_Clear_Screen(newcon);
Mono_Bring_To_Top(mono_globals, newcon);
fileobject->FsContext = (void*)avail;
}
}
break;
/*
** Closing the file occurs when the last reference to the object has been
** severed.
*/
case IRP_MJ_CLOSE:
if (currentindex != -1) {
Mono_Init_Buffer(&mono_globals->Control[currentindex]);
fileobject->FsContext = NULL;
}
break;
/*
** This is called prior to closing the file.
*/
case IRP_MJ_CLEANUP:
break;
/*
** All the special I/O control functions route through this
** IRP message.
*/
case IRP_MJ_DEVICE_CONTROL:
ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
switch (ioControlCode) {
/*
** Set a driver flag.
*/
case IOCTL_MONO_SET_FLAG:
if (inputBufferLength == sizeof(int)) {
FLAG_SET(control, *(int*)ioBuffer);
} else {
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
}
break;
/*
** Clear a driver flag.
*/
case IOCTL_MONO_CLEAR_FLAG:
if (inputBufferLength == sizeof(int)) {
FLAG_CLEAR(control, *(int*)ioBuffer);
} else {
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
}
break;
/*
** Fill a region of the screen with a specific attribute.
*/
case IOCTL_MONO_FILL_ATTRIB:
if (inputBufferLength == sizeof(int)*5) {
int x,y,w,h,a;
x = *(((int*)ioBuffer) + 0);
y = *(((int*)ioBuffer) + 1);
w = *(((int*)ioBuffer) + 2);
h = *(((int*)ioBuffer) + 3);
a = *(((int*)ioBuffer) + 4);
Mono_Fill_Attribute(control, x, y, w, h, a);
} else {
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
}
break;
/*
** Reset the sub-window back to full screen.
*/
case IOCTL_MONO_RESET_WINDOW:
control->WinX = 0;
control->WinY = 0;
control->WinW = MONO_WIDTH;
control->WinH = MONO_HEIGHT;
control->XPos = 0;
control->YPos = 0;
break;
/*
** Create a sub-window that restricts mono output to.
*/
case IOCTL_MONO_SET_WINDOW:
if (inputBufferLength == sizeof(int)*4) {
control->WinX = *(((int*)ioBuffer) + 0);
if (control->WinX < 0) control->WinX = 0;
if (control->WinX >= MONO_WIDTH) control->WinX = MONO_WIDTH-1;
control->WinY = *(((int*)ioBuffer) + 1);
if (control->WinY < 0) control->WinY = 0;
if (control->WinY >= MONO_HEIGHT) control->WinY = MONO_HEIGHT-1;
control->WinW = *(((int*)ioBuffer) + 2);
if (control->WinW < 1) control->WinW = 1;
if (control->WinW > MONO_WIDTH-control->WinX) control->WinW = MONO_WIDTH-control->WinX;
control->WinH = *(((int*)ioBuffer) + 3);
if (control->WinH < 1) control->WinH = 1;
if (control->WinH > MONO_HEIGHT-control->WinY) control->WinH = MONO_HEIGHT-control->WinY;
control->XPos = 0;
control->YPos = 0;
} else {
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
}
break;
/*
** Display the help screen (signon banner).
*/
case IOCTL_MONO_HELP_SCREEN:
Display_Signon_Banner(control);
break;
/*
** Bring the mono page to the visible top, but only if it
** or the current visible top is not currently locked.
*/
case IOCTL_MONO_BRING_TO_TOP:
Mono_Bring_To_Top(mono_globals, control);
break;
/*
** Scroll the screen up one row.
*/
case IOCTL_MONO_SCROLL:
Mono_Scroll(control);
break;
/*
** Scroll the screen left one column.
*/
case IOCTL_MONO_PAN:
Mono_Pan(control);
break;
/*
** Set the cursor position to the coordinates specified.
*/
case IOCTL_MONO_SET_CURSOR:
if (inputBufferLength == sizeof(int)*2) {
control->XPos = *(int*)ioBuffer;
if (control->XPos < 0) control->XPos = 0;
if (control->XPos >= control->WinW) control->XPos = control->WinW-1;
control->YPos = *(((int*)ioBuffer) + 1);
if (control->YPos < 0) control->YPos = 0;
if (control->YPos >= control->WinH) control->YPos = control->WinH-1;
} else {
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
}
break;
/*
** Print text without any formatting processing.
*/
case IOCTL_MONO_PRINT_RAW:
Mono_Print_Raw(control, ioBuffer, inputBufferLength);
break;
/*
** Clear the screen to blank (using the default attribute).
*/
case IOCTL_MONO_CLEAR_SCREEN:
Mono_Clear_Screen(control);
break;
/*
** Set the default attribute to use for subsiquent output.
*/
case IOCTL_MONO_SET_ATTRIBUTE:
control->Attribute = *(char *)ioBuffer;
break;
/*
** Lock the mono page and return a user-space mapped pointer to
** it.
*/
case IOCTL_MONO_LOCK:
if (control->LockPtr == NULL) {
control->LockPtr = Mono_Fetch_Ptr(mono_globals, control);
}
if (control->LockPtr != NULL) {
*(void**)ioBuffer = control->LockPtr;
control->LockCount++;
Irp->IoStatus.Information = sizeof(void *);
} else {
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
}
break;
/*
** Unlock the mono page.
*/
case IOCTL_MONO_UNLOCK:
if (control->LockCount > 0) {
control->LockCount--;
if (control->LockCount == 0) {
Irp->IoStatus.Status = ZwUnmapViewOfSection((HANDLE) -1, control->LockPtr);
control->LockPtr = NULL;
}
}
break;
/*
** Unrecognized control code results in an error return value.
*/
default:
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
break;
}
break;
}
/*
** Only if the context drawn to is the currently visible one, will the
** cursor position be updated.
*/
if (currentindex == mono_globals->CurrentVisible) {
Mono_Update_Cursor(mono_globals);
}
KeSetEvent(&mono_globals->SyncEvent, 0, FALSE);
ntStatus = Irp->IoStatus.Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return(ntStatus);
}
/***********************************************************************************************
* Mono_Unload -- Unloads the driver from the system. *
* *
* This will free any resources allocated by this driver, break any symbolic link, and *
* delete the driver object from the system. Effectively, this is the suicide function *
* for the MGA driver. *
* *
* INPUT: driver -- Pointer to the driver object to delete. *
* *
* OUTPUT: none *
* *
* WARNINGS: Don't use the driver after calling this function. *
* *
* HISTORY: *
* 01/06/1997 JLB : Created. *
*=============================================================================================*/
void Mono_Unload(PDRIVER_OBJECT DriverObject)
{
UNICODE_STRING link_string;
Mono_Free_Resources(DriverObject);
RtlInitUnicodeString(&link_string, SYMBOLIC_NAME);
IoDeleteSymbolicLink(&link_string);
if (DriverObject->DeviceObject != NULL) {
IoDeleteDevice(DriverObject->DeviceObject);
}
}
/***********************************************************************************************
* Mono_Detect_MGA_Adapter -- Try to detec the MGA adapter. *
* *
* Tries to find the MGA adaptor by writing a few bytes to the CRTC register and checking *
* if they return a corresponding value. *
* *
* INPUT: none *
* *
* OUTPUT: bool; Was the MGA card deteced? *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 01/05/1997 JLB : Created. *
*=============================================================================================*/
BOOLEAN Mono_Detect_MGA_Adapter(void)
{
unsigned char * crtc_registerss;
/*
** Get address to the CRTC registers.
*/
crtc_registerss = Mono_Get_Address_Ptr(RtlConvertUlongToLargeInteger(CRTC_REGISTER), 1, 2);
if (crtc_registerss != NULL) {
/*
** Set the mono cursor position and see if it changed. If so, then
** presume that the MGA adapter is present.
*/
WRITE_PORT_UCHAR(crtc_registerss, 0x0F);
WRITE_PORT_UCHAR(crtc_registerss+1, 0x55);
if (READ_PORT_UCHAR(crtc_registerss+1) != 0x55) {
return(FALSE);
}
WRITE_PORT_UCHAR(crtc_registerss+1, 0xAA);
if (READ_PORT_UCHAR(crtc_registerss+1) != 0xAA) {
return(FALSE);
}
WRITE_PORT_UCHAR(crtc_registerss+1, 0x00);
return(TRUE);
}
return(FALSE);
}
/***********************************************************************************************
* Mono_Get_Address_Ptr -- Converts a physical address into a usable pointer. *
* *
* This routine will take the physical address specified and convert it into a pointer that *
* can be used to reference the address specified. *
* *
* INPUT: address -- The physical address to convert. *
* *
* space -- The address space that the specified address is in. 0 means memory, *
* 1 means I/O space (ports). *
* *
* length -- The length of the memory that will be referenced. *
* *
* OUTPUT: Returns with a usable pointer to the memory specified or NULL if it could not be *
* processed. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 01/05/1997 JLB : Created. *
*=============================================================================================*/
void * Mono_Get_Address_Ptr(PHYSICAL_ADDRESS address, unsigned long space, unsigned long length)
{
PHYSICAL_ADDRESS logical_address;
void * usable_ptr = NULL;
/*
** Translate a bus specific address into a logical system address.
*/
if (HalTranslateBusAddress(Isa, 0, address, &space, &logical_address)) {
/*
** If the space value is zero, then this idicates that a call to
** MmMapIoSpace is required. This is usually required for port addresses.
*/
if (space == 0) {
usable_ptr = MmMapIoSpace(logical_address, length, FALSE);
} else {
usable_ptr = (void *)logical_address.LowPart;
}
}
return(usable_ptr);
}
/***********************************************************************************************
* Mono_Claim_Resources -- Claims resources for the MGA driver. *
* *
* This routine will scan the registry in order to claim the hardware resources needed by *
* this MGA display driver. If any of the required resources have already been claimed *
* in an exclusive mode, then the driver should not load. *
* *
* INPUT: driver -- Pointer to the driver object. *
* *
* OUTPUT: bool; Were the required resources claimed successfully? *
* *
* WARNINGS: If the resources were not claimed, then the driver should not load. *
* *
* HISTORY: *
* 01/06/1997 JLB : Created. *
*=============================================================================================*/
BOOLEAN Mono_Claim_Resources(PDRIVER_OBJECT driver)
{
unsigned long resource_list_size = 0;
PCM_RESOURCE_LIST resource_list = NULL;
/*
** Allocate a resource descriptor list. This must be allocated because it is a variable
** size structure and the CM_RESOURCE_LIST is typedef'd as single entry lists (which
** is insufficient for our purposes).
*/
resource_list_size = sizeof(CM_RESOURCE_LIST) + (sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * (ARRAY_SIZE(MonoResources) - 1));
resource_list = ExAllocatePool(PagedPool, resource_list_size);
if (resource_list != NULL) {
UNICODE_STRING class_name;
PCM_PARTIAL_RESOURCE_DESCRIPTOR partial_resource_list;
BOOLEAN conflict_flag;
unsigned long index;
RtlZeroMemory(resource_list, resource_list_size);
/*
** There is one resource list (although multiple resources). They are
** all located on the Isa bus number 0.
*/
resource_list->Count = 1;
resource_list->List[0].InterfaceType = Isa;
resource_list->List[0].BusNumber = 0;
resource_list->List[0].PartialResourceList.Count = ARRAY_SIZE(MonoResources);
/*
** Fill in the resrouce list with the resources required by the MGA
** device driver.
*/
partial_resource_list = &resource_list->List[0].PartialResourceList.PartialDescriptors[0];
for (index = 0; index < ARRAY_SIZE(MonoResources); index++) {
if (MonoResources[index].AddressSpace) {
partial_resource_list->Type = CmResourceTypePort;
partial_resource_list->Flags = CM_RESOURCE_PORT_IO;
partial_resource_list->u.Port.Start = RtlConvertUlongToLargeInteger(MonoResources[index].PhysicalAddress);
partial_resource_list->u.Port.Length = MonoResources[index].Length;
} else {
partial_resource_list->Type = CmResourceTypeMemory;
partial_resource_list->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
partial_resource_list->u.Memory.Start = RtlConvertUlongToLargeInteger(MonoResources[index].PhysicalAddress);
partial_resource_list->u.Memory.Length = MonoResources[index].Length;
}
if (MonoResources[index].RangeSharable) {
partial_resource_list->ShareDisposition = CmResourceShareShared;
} else {
partial_resource_list->ShareDisposition = CmResourceShareDeviceExclusive;
}
partial_resource_list++;
}
/*
** Now that the resource list has been filled in, try to request the resources
** from the system. It does this by comparing the requested resources with those
** that have been claimed in the registry.
*/
RtlInitUnicodeString(&class_name, RESOURCE_NAME);
IoReportResourceUsage(&class_name, driver, resource_list, resource_list_size, NULL, NULL, 0, FALSE, &conflict_flag);
ExFreePool(resource_list);
return(conflict_flag == FALSE);
}
return(FALSE);
}
/***********************************************************************************************
* Mono_Free_Resources -- Free reported hardware usage. *
* *
* This routine will clear the registry of the reported hardware usage by the mono *
* display driver. It should be called only when the driver is being unloaded. *
* *
* INPUT: driver -- Pointer to the driver object. *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 01/06/1997 JLB : Created. *
*=============================================================================================*/
void Mono_Free_Resources(PDRIVER_OBJECT driver)
{
UNICODE_STRING class_name;
BOOLEAN found_conflict;
CM_RESOURCE_LIST resource_list = {0};
RtlInitUnicodeString(&class_name, RESOURCE_NAME);
IoReportResourceUsage(&class_name, driver, &resource_list, sizeof(resource_list), NULL, NULL, 0, FALSE, &found_conflict);
}
/***********************************************************************************************
* Mono_Update_Cursor -- Updates the CRTC cursor to reflect current visible page. *
* *
* Use this routine to update the display cursor to match the recorded cursor position *
* for the currently visible page. *
* *
* INPUT: device -- Pointer to the mono driver globals. *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 01/06/1997 JLB : Created. *
*=============================================================================================*/
void Mono_Update_Cursor(MonoGlobals * device)
{
int pos;
BuffControl * control = &device->Control[device->CurrentVisible];
pos = control->XPos + control->WinX + ((control->YPos+control->WinY) * MONO_WIDTH);
WRITE_PORT_UCHAR(device->CRTCRegisters, 0x0E);
WRITE_PORT_UCHAR(device->CRTCRegisters+1, (unsigned char)(pos>>8));
WRITE_PORT_UCHAR(device->CRTCRegisters, 0x0F);
WRITE_PORT_UCHAR(device->CRTCRegisters+1, (unsigned char)(pos & 0xFF));
}
/***********************************************************************************************
* Mono_Print -- Prints text (with formatting) to mono screen. *
* *
* This routine will take the text specified and print it to the monochrome screen. If *
* there are any formatting characters present, then they will be processed accordingly. *
* *
* INPUT: control -- Poitner to the buffer to print to. *
* *
* string -- Pointer to the string to print. *
* *
* length -- The length of the string to print. *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 01/04/1997 JLB : Created. *
*=============================================================================================*/
void Mono_Print(BuffControl * control, unsigned char * string, unsigned long length)
{
if (control != NULL) {
unsigned char space = ' ';
int original_x = control->XPos;
while (length > 0) {
int x,y;
unsigned char * blockstart;
int blocklen;
unsigned char bchar; // Breaking character.
/*
** Scan for a block of contiguous non-formatting characters to print.
*/
blockstart = string;
blocklen = 0;
bchar = '\0';
x = control->XPos;
while (length > 0 && bchar == '\0') {
bchar = *string++;
length--;
/*
** Detect if this character is special and requires
** formatting control rather than simple displaying.
*/
switch (bchar) {
case '\b': // Backspace
case '\a': // Audible bell
case '\t': // Horizontal tab
case '\f': // Formfeed
case '\n': // Linefeed
case '\v': // Vertical tab
break;
/*
** If a <CR><LF> pair is detected, then treat it
** just as if it were a '\n'. This is for backward
** compatibility. If it is just a '\r', then it
** functions similarly to the '\n' code.
*/
case '\r':
if (length > 0 && *string == '\n') {
length--;
string++;
bchar = '\n';
}
break;
/*
** If not a valid formatting character, then clear out the break
** character variable so that processing will continue.
*/
default:
blocklen++;
bchar = '\0';
break;
}
/*
** If wrapping at right margin is desired, then check for
** this condition and force a line break if margin is reached.
*/
if (bchar == '\0' && IS_FLAG_ON(control, MONOFLAG_WRAP)) {
x++;
if (x >= control->WinW) {
bchar = '\n';
}
}
}
/*
** If a block has been scanned, then print it at this time.
*/
if (blocklen > 0) {
Mono_Print_Raw(control, blockstart, blocklen);
}
/*
** Conveniently get the cursor position into working variables.
** This helps because many of the formatting characters change
** the cursor position.
*/
x = control->XPos;
y = control->YPos;
/*
** If a formatting character was found, then process it at this
** time.
*/
switch (bchar) {
/*
** Backspace moves the cursor back one space (erasing what was there).
*/
case '\b':
if (x > 0) {
x--;
control->XPos = x;
Mono_Print_Raw(control, &space, 1);
control->XPos = x;
}
break;
/*
** Formfeed -- clears the screen.
*/
case '\f':
Mono_Clear_Screen(control);
break;
/*
** Linefeed -- in the tradition of C, this actually translates
** into a functional <CR><LF> pair.
*/
case '\n':
x = 0;
y++;
if (y >= control->WinH) {
Mono_Scroll(control);
y--;
}
control->XPos = x;
control->YPos = y;
break;
/*
** A <CR> will move the cursor down one row and back to the column
** position that the print started at.
*/
case '\r':
x = original_x;
y++;
if (y >= control->WinH) {
Mono_Scroll(control);
y--;
}
control->XPos = x;
control->YPos = y;
break;
/*
** Horizontal tab
*/
case '\t':
Mono_Print_Raw(control, &space, 1);
break;
/*
** Unrecognized formatting character -- ignore it.
*/
default:
break;
}
}
}
}
/***********************************************************************************************
* Mono_Scroll -- Scroll the mono screen up one line. *
* *
* Use this routine to scroll the mono screen up one line. The bottom line will be filled *
* with blanks. The cursor position is moved up one line as well. *
* *
* INPUT: control -- Pointer to the buffer to scroll. *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 01/04/1997 JLB : Created. *
*=============================================================================================*/
void Mono_Scroll(BuffControl * control)
{
if (control != NULL) {
int j;
unsigned short * vidmem = control->Buffer;
unsigned short blank = BUILD_MONO_CHAR(' ', control->Attribute);
unsigned short * lineptr = vidmem + (control->WinY*MONO_WIDTH) + control->WinX;
/*
** Move every line of the sub-window.
*/
for (j = 0; j < control->WinH-1; j++) {
RtlCopyMemory(lineptr, lineptr+MONO_WIDTH, control->WinW * sizeof(unsigned short));
lineptr += MONO_WIDTH;
}
/*
** Fill the bottom row with blanks.
*/
for (j = 0; j < control->WinW; j++) {
*lineptr++ = blank;
}
/*
** The cursor position moves with the scroll, but limited to the
** edge of the window.
*/
control->YPos -= 1;
if (control->YPos < 0) {
control->YPos = 0;
}
}
}
/***********************************************************************************************
* Mono_Pan -- Pan the mono screen over one column. *
* *
* This will scroll (horizontally) the monochrome screen. The new column will be filled *
* with blank spaces. *
* *
* INPUT: control -- Pointer to the buffer to pan. *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 01/04/1997 JLB : Created. *
*=============================================================================================*/
void Mono_Pan(BuffControl * control)
{
if (control != NULL) {
unsigned short * vidmem = control->Buffer;
unsigned short blank = BUILD_MONO_CHAR(' ', control->Attribute);
int j;
/*
** Move the video memory over by one column.
*/
for (j = 0; j < control->WinH; j++) {
unsigned short * linestart = vidmem + ((control->WinY+j)*MONO_WIDTH) + control->WinX;
RtlMoveMemory(linestart, linestart+1, (control->WinW-1) * sizeof(unsigned short));
*(linestart+control->WinW-1) = blank;
}
/*
** The cursor position moves as well, but limited to the window
** margin.
*/
control->XPos -= 1;
if (control->XPos < 0) {
control->XPos = 0;
}
}
}
/***********************************************************************************************
* Mono_Print_Raw -- Print text (without processing) to mono screen. *
* *
* This is a low level routine that will not process the characters submitted, but merely *
* draw them to the monochrome screen. The output will not wrap at right margin nor will *
* it scroll the screen when it tries to print past the bottom right character position. *
* This routine can be used to output characters that have a visual image even though they *
* line up with formatting control characters. *
* *
* INPUT: control -- Pointer to the buffer to print to. *
* *
* string -- Pointer to the string to output. *
* *
* length -- The length of the string in characters. *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 01/04/1997 JLB : Created. *
*=============================================================================================*/
void Mono_Print_Raw(BuffControl * control, unsigned char * string, unsigned long length)
{
if (control != NULL) {
unsigned short * vidmem = control->Buffer + (control->XPos+control->WinX) + ((control->YPos+control->WinY)*MONO_WIDTH);
int x = control->XPos;
while (length > 0) {
*vidmem++ = BUILD_MONO_CHAR(*string++, control->Attribute);
x++;
length--;
/*
** Don't allow the cursor to extend past the right margin.
*/
if (x >= control->WinW) {
x--;
vidmem--;
}
}
control->XPos = x;
}
}
/***********************************************************************************************
* Mono_Clear_Screen -- Clears the monochrome screen & homes cursor. *
* *
* This will erase the monochrome screen and move the output cursor to the upper left *
* corner. *
* *
* INPUT: control -- Pointer to the buffer to clear. *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 01/04/1997 JLB : Created. *
*=============================================================================================*/
void Mono_Clear_Screen(BuffControl * control)
{
if (control != NULL) {
int yindex;
unsigned short blank = BUILD_MONO_CHAR(' ', control->Attribute);
unsigned short * rowptr = control->Buffer + (control->WinY * MONO_WIDTH) + control->WinX;
for (yindex = 0; yindex < control->WinH; yindex++) {
int xindex;
unsigned short * lineptr = rowptr;
for (xindex = 0; xindex < control->WinW; xindex++) {
*lineptr++ = blank;
}
rowptr += MONO_WIDTH;
}
control->XPos = 0;
control->YPos = 0;
}
}
/***********************************************************************************************
* Mono_Printf -- Print formatted text to the mono device. *
* *
* Prints formatted text to the monochrome device specified. *
* *
* INPUT: control -- Pointer to the buffer to print to. *
* *
* text -- Pointer to the text to display. *
* *
* ... -- Any optional parameters needed by the string. *
* *
* OUTPUT: none *
* *
* WARNINGS: The final formatted string is limited to 1024 characters long. *
* *
* HISTORY: *
* 01/04/1997 JLB : Created. *
*=============================================================================================*/
void Mono_Printf(BuffControl * control, char const * text, ...)
{
if (control != NULL) {
char buf[MONO_WIDTH*MONO_HEIGHT + 1];
va_list ap;
va_start(ap, text);
vsprintf(buf, text, ap);
Mono_Print(control, buf, strlen(buf));
va_end(ap);
}
}
/***********************************************************************************************
* Mono_Set_View_Pos -- Set the mono display ram view offset. *
* *
* Set the CRTC register for the monochrome display to the offset specified. The card *
* defaults to viewing offset 0 (i.e. $B0000 absolute RAM address). *
* *
* INPUT: device -- The monochrome device global data. *
* *
* pos -- The offset position to set the view to. *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 01/04/1997 JLB : Created. *
*=============================================================================================*/
void Mono_Set_View_Pos(MonoGlobals * device, int pos)
{
if (device != NULL) {
WRITE_PORT_UCHAR(device->CRTCRegisters, 0x0C);
WRITE_PORT_UCHAR(device->CRTCRegisters+1, (unsigned char)(pos >> 8));
WRITE_PORT_UCHAR(device->CRTCRegisters, 0x0D);
WRITE_PORT_UCHAR(device->CRTCRegisters+1, (unsigned char)(pos & 0xFF));
}
}
/***********************************************************************************************
* Mono_Bring_To_Top -- Brings the mono page to the visible top of the display stack. *
* *
* This routine will take the page specified and bring it to the top of the display stack. *
* Effectively, this makes it visible. *
* *
* INPUT: device -- Pointer to the mono device globals. *
* *
* page -- Pointer to the page that is to be displayed. *
* *
* OUTPUT: none *
* *
* WARNINGS: If either the visible page or the one specified is locked, then no action *
* can be performed. *
* *
* HISTORY: *
* 01/06/1997 JLB : Created. *
*=============================================================================================*/
void Mono_Bring_To_Top(MonoGlobals * device, BuffControl * page)
{
BuffControl * visible_page = &device->Control[device->CurrentVisible];
if (page == NULL || page->Buffer == visible_page->Buffer) return;
/*
** If either the one trying to be brought to the front or the
** one already displayed is locked, then the display stack
** cannot be modified.
*/
if (page->LockCount > 0 || visible_page->LockCount > 0) return;
/*
** Swap the contents of the page buffers and then swap the page buffer
** pointers.
*/
{
unsigned short temp[MONO_WIDTH*MONO_HEIGHT];
void * tempptr;
int tempindex;
RtlCopyMemory(temp, page->Buffer, MONO_PAGE_SIZE);
RtlCopyMemory(page->Buffer, visible_page->Buffer, MONO_PAGE_SIZE);
RtlCopyMemory(visible_page->Buffer, temp, MONO_PAGE_SIZE);
tempptr = page->Buffer;
page->Buffer = visible_page->Buffer;
visible_page->Buffer = tempptr;
}
device->CurrentVisible = (page - &device->Control[0]);
Mono_Update_Cursor(device);
}
/***********************************************************************************************
* Display_Signon_Banner -- Display the signon banner at driver start. *
* *
* This displays the signon banner that the driver displays when it first starts. *
* *
* INPUT: control -- Pointer to the buffer that the signon banner will be displayed to. *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 01/06/1997 JLB : Created. *
*=============================================================================================*/
void Display_Signon_Banner(BuffControl * control)
{
Mono_Printf(control,
"\fMono Display Driver [monodrvr.sys] -- NT Kernel Mode Device Driver\n"
"Version: 1.0 -- (" __DATE__ " " __TIME__ ")\n"
"Device Name: " A_DEVICE_NAME "\n"
"Symbolic Link: " A_SYMBOLIC_NAME " (\"\\\\.\\MONO\")\n\n");
Mono_Printf(control, "Supporting IOCTL Services:\n");
Mono_Printf(control, "--------------------------\n");
Mono_Printf(control, " 0x%08X IOCTL_MONO_HELP_SCREEN\n", IOCTL_MONO_HELP_SCREEN);
Mono_Printf(control, " 0x%08X IOCTL_MONO_CLEAR_SCREEN\n", IOCTL_MONO_CLEAR_SCREEN);
Mono_Printf(control, " 0x%08X IOCTL_MONO_PRINT_RAW(char * text, int length)\n", IOCTL_MONO_PRINT_RAW);
Mono_Printf(control, " 0x%08X IOCTL_MONO_SET_CURSOR(int x, int y)\n", IOCTL_MONO_SET_CURSOR);
Mono_Printf(control, " 0x%08X IOCTL_MONO_SCROLL\n", IOCTL_MONO_SCROLL);
Mono_Printf(control, " 0x%08X IOCTL_MONO_BRING_TO_TOP\n", IOCTL_MONO_BRING_TO_TOP);
Mono_Printf(control, " 0x%08X IOCTL_MONO_SET_ATTRIBUTE(char attrib)\n", IOCTL_MONO_SET_ATTRIBUTE);
Mono_Printf(control, " 0x%08X IOCTL_MONO_PAN\n", IOCTL_MONO_PAN);
Mono_Printf(control, " 0x%08X IOCTL_MONO_LOCK [returns mono memory address]\n", IOCTL_MONO_LOCK);
Mono_Printf(control, " 0x%08X IOCTL_MONO_UNLOCK\n", IOCTL_MONO_UNLOCK);
Mono_Printf(control, " 0x%08X IOCTL_MONO_SET_WINDOW(int x, int y, int w, int h)\n", IOCTL_MONO_SET_WINDOW);
Mono_Printf(control, " 0x%08X IOCTL_MONO_RESET_WINDOW\n", IOCTL_MONO_RESET_WINDOW);
Mono_Printf(control, " 0x%08X IOCTL_MONO_SET_FLAG(int flag)\n", IOCTL_MONO_SET_FLAG);
Mono_Printf(control, " 0x%08X IOCTL_MONO_CLEAR_FLAG(int flag)\n", IOCTL_MONO_CLEAR_FLAG);
Mono_Printf(control, " 0x%08X IOCTL_MONO_FILL_ATTRIB(int x, int y, int w, int h, int attrib)\n", IOCTL_MONO_FILL_ATTRIB);
}
/***********************************************************************************************
* Mono_Fetch_Ptr -- Fetch a USER address space pointer to mono buffer. *
* *
* This routine will create a user address space pointer (one that the ring 3 program can *
* use). *
* *
* INPUT: device -- Pointer to the mono device globals. *
* *
* page -- Pointer to the page that a pointer will be generated for. *
* *
* OUTPUT: Returns with a user pointer to the monochrome card memory that is represented *
* by the page specified. *
* *
* WARNINGS: This effectively locks the buffer so that it cannot be swapped. *
* *
* HISTORY: *
* 01/06/1997 JLB : Created. *
*=============================================================================================*/
void * Mono_Fetch_Ptr(MonoGlobals * device, BuffControl * page)
{
UNICODE_STRING memory_unicode_string;
OBJECT_ATTRIBUTES object_attribute;
HANDLE section_handle = NULL;
NTSTATUS error;
void * retval = NULL;
/*
** Try to open the PhysicalMemory section. This will be needed when mapping the
** physical memory 'file' to an accessable address range. First create a physical
** memory object and then convert that object into a handle value.
*/
RtlInitUnicodeString(&memory_unicode_string, L"\\Device\\PhysicalMemory");
InitializeObjectAttributes(&object_attribute, &memory_unicode_string, OBJ_CASE_INSENSITIVE, (HANDLE)NULL, (PSECURITY_DESCRIPTOR)NULL);
error = ZwOpenSection(&section_handle, SECTION_ALL_ACCESS, &object_attribute);
if (NT_SUCCESS(error)) {
PHYSICAL_ADDRESS logical_base_address;
ULONG in_io_space = 0;
//
// Translate the physical addresses.
//
if (HalTranslateBusAddress(Isa, 0, RtlConvertUlongToLargeInteger(MONO_MEMORY + (page->Buffer - device->DisplayMemory) * sizeof(unsigned short)), &in_io_space, &logical_base_address)) {
PVOID virtual_address = NULL;
ULONG viewlength = MONO_MEM_LENGTH;
PHYSICAL_ADDRESS view_base = logical_base_address;
//
// Map the section
//
error = ZwMapViewOfSection(section_handle, (HANDLE) -1, &virtual_address, 0L, viewlength, &view_base, &viewlength, ViewShare, 0, PAGE_READWRITE | PAGE_NOCACHE);
if (NT_SUCCESS(error)) {
//
// Mapping the section above rounded the physical address down to the
// nearest 64 K boundary. Now return a virtual address that sits where
// we want by adding in the offset from the beginning of the section.
//
(ULONG) virtual_address += (ULONG)logical_base_address.LowPart - (ULONG)view_base.LowPart;
retval = virtual_address;
}
}
/*
** Close the zone handle before exiting.
*/
ZwClose(section_handle);
}
return(retval);
}
/***********************************************************************************************
* Mono_Init_Buffer -- Initialize a mono buffer to known (unused) state. *
* *
* This is equivalent to a constructor for the BuffControl object. It resets all values *
* that it can to a known state. *
* *
* INPUT: buffer -- Pointer to the buffer object to initialize. *
* *
* OUTPUT: none *
* *
* WARNINGS: The internal MGA RAM pointer is not reset by this routine. This value is *
* managed at the driver level, not the buffer object level. *
* *
* HISTORY: *
* 01/06/1997 JLB : Created. *
*=============================================================================================*/
void Mono_Init_Buffer(BuffControl * buffer)
{
buffer->XPos = 0;
buffer->YPos = 0;
buffer->Attribute = DEFAULT_ATTRIBUTE;
buffer->LockPtr = NULL;
buffer->LockCount = 0;
buffer->Allocated = FALSE;
buffer->WinX = 0;
buffer->WinY = 0;
buffer->WinW = MONO_WIDTH;
buffer->WinH = MONO_HEIGHT;
buffer->Flags = 0;
}
/***********************************************************************************************
* Mono_Fill_Attribute -- Fills rectangle with attribute specified. *
* *
* This routine will set the attribute for the region specified. It can be used to *
* hightlight or otherwise perform some cheesy effects without altering the text that *
* is already present. *
* *
* INPUT: x,y,w,h -- Coordinates and dimensions of the rectangle to alter. *
* *
* attrib -- The attribute to set for the rectangle specified. *
* *
* OUTPUT: none *
* *
* WARNINGS: It is possible to set an attribute such that the text 'disappears'. *
* *
* HISTORY: *
* 01/06/1997 JLB : Created. *
*=============================================================================================*/
void Mono_Fill_Attribute(BuffControl * control, int x, int y, int w, int h, int attrib)
{
if (control != NULL) {
int yindex;
unsigned short blank = BUILD_MONO_CHAR(' ', control->Attribute);
unsigned short * rowptr;
/*
** Clip the parameters to legal values.
*/
if (x < 0) x = 0;
if (x >= control->WinW) x = control->WinW-1;
if (y < 0) y = 0;
if (y >= control->WinH) y = control->WinH-1;
if (w < 1) w = 1;
if (w > control->WinW-x) w = control->WinW-x;
if (h < 1) h = 1;
if (h > control->WinH-y) h = control->WinH-y;
rowptr = control->Buffer + ((control->WinY + y) * MONO_WIDTH) + control->WinX + x;
for (yindex = 0; yindex < h; yindex++) {
int xindex;
unsigned short * lineptr = rowptr;
for (xindex = 0; xindex < w; xindex++) {
*lineptr = BUILD_MONO_CHAR(*lineptr, attrib);
lineptr++;
}
rowptr += MONO_WIDTH;
}
}
}