You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
504 lines
14 KiB
504 lines
14 KiB
/*++
|
|
|
|
Copyright (c) 1991 - 2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
### ## # ## ##### #### ### ##### #### ##### #####
|
|
## # ## ### ## ## ## ## ## # ## ## ## # ## ## ## ##
|
|
### ## ### ## ## ## ## ### ## ## ## ## ## ## ##
|
|
### ## # # ## ## ## ## ### ## ## ## ## ## ## ##
|
|
### ### ### ## ## ## ### ##### ## ##### #####
|
|
# ## ### ### ## ## ## # ## ## ## ## # ## ##
|
|
### ## ## ##### #### ### ## ## #### ## ##
|
|
|
|
Abstract:
|
|
|
|
This module contains the entire implementation of
|
|
the local display miniport for the ServerWorks
|
|
CSB5 server chip set.
|
|
|
|
Author:
|
|
|
|
Wesley Witt (wesw) 1-Oct-2001
|
|
|
|
Environment:
|
|
|
|
Kernel mode only.
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
#include "swdisp.h"
|
|
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(INIT,DriverEntry)
|
|
#endif
|
|
|
|
|
|
|
|
NTSTATUS
|
|
SaDispHwInitialize(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN PVOID DeviceExtensionIn,
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResources,
|
|
IN ULONG PartialResourceCount
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is the driver's entry point, called by the I/O system
|
|
to load the driver. The driver's entry points are initialized and
|
|
a mutex to control paging is initialized.
|
|
|
|
In DBG mode, this routine also examines the registry for special
|
|
debug parameters.
|
|
|
|
Arguments:
|
|
DeviceObject - Miniport's device object
|
|
Irp - Current IRP in progress
|
|
DeviceExtensionIn - Miniport's device extension
|
|
PartialResources - List of resources that are assigned to the miniport
|
|
PartialResourceCount - Number of assigned resources
|
|
|
|
Return Value:
|
|
|
|
NT status code
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG i;
|
|
PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION) DeviceExtensionIn;
|
|
PCM_PARTIAL_RESOURCE_DESCRIPTOR Resource = NULL;
|
|
|
|
|
|
for (i=0; i<PartialResourceCount; i++) {
|
|
if (PartialResources[i].Type == CmResourceTypeMemory) {
|
|
Resource = &PartialResources[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (Resource == NULL) {
|
|
REPORT_ERROR( SA_DEVICE_DISPLAY, "Missing memory resource", STATUS_UNSUCCESSFUL );
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
DeviceExtension->VideoMemBase = (PUCHAR) SaPortGetVirtualAddress(
|
|
DeviceExtension,
|
|
Resource->u.Memory.Start,
|
|
Resource->u.Memory.Length
|
|
);
|
|
if (DeviceExtension->VideoMemBase == NULL) {
|
|
REPORT_ERROR( SA_DEVICE_DISPLAY, "SaPortGetVirtualAddress failed", STATUS_NO_MEMORY );
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
SaDispDeviceIoctl(
|
|
IN PVOID DeviceExtension,
|
|
IN PIRP Irp,
|
|
IN PVOID FsContext,
|
|
IN ULONG FunctionCode,
|
|
IN PVOID InputBuffer,
|
|
IN ULONG InputBufferLength,
|
|
IN PVOID OutputBuffer,
|
|
IN ULONG OutputBufferLength
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine processes the device control requests for the
|
|
local display miniport.
|
|
|
|
Arguments:
|
|
|
|
DeviceExtension - Miniport's device extension
|
|
FunctionCode - Device control function code
|
|
InputBuffer - Pointer to the user's input buffer
|
|
InputBufferLength - Length in bytes of the input buffer
|
|
OutputBuffer - Pointer to the user's output buffer
|
|
OutputBufferLength - Length in bytes of the output buffer
|
|
|
|
Return Value:
|
|
|
|
NT status code.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
PSA_DISPLAY_CAPS DeviceCaps;
|
|
|
|
|
|
switch (FunctionCode) {
|
|
case FUNC_SA_GET_VERSION:
|
|
*((PULONG)OutputBuffer) = SA_INTERFACE_VERSION;
|
|
break;
|
|
|
|
case FUNC_SA_GET_CAPABILITIES:
|
|
DeviceCaps = (PSA_DISPLAY_CAPS)OutputBuffer;
|
|
DeviceCaps->SizeOfStruct = sizeof(SA_DISPLAY_CAPS);
|
|
DeviceCaps->DisplayType = SA_DISPLAY_TYPE_BIT_MAPPED_LCD;
|
|
DeviceCaps->CharacterSet = SA_DISPLAY_CHAR_ASCII;
|
|
DeviceCaps->DisplayHeight = DISPLAY_HEIGHT;
|
|
DeviceCaps->DisplayWidth = DISPLAY_WIDTH;
|
|
break;
|
|
|
|
default:
|
|
Status = STATUS_NOT_SUPPORTED;
|
|
REPORT_ERROR( SA_DEVICE_DISPLAY, "Unsupported device control", Status );
|
|
break;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
UCHAR TestMask[128] =
|
|
{
|
|
0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01,0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01,
|
|
0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01,0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01,
|
|
0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01,0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01,
|
|
0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01,0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01,
|
|
0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01,0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01,
|
|
0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01,0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01,
|
|
0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01,0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01,
|
|
0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01,0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01
|
|
};
|
|
|
|
|
|
ULONG
|
|
TransformBitmap(
|
|
PUCHAR Bits,
|
|
ULONG Width,
|
|
ULONG Height,
|
|
PUCHAR NewBits
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The TransformBitmap() function morphs the input bitmap from a
|
|
normal bitmap that has it's pixel bits organized as sequential
|
|
bits starting from coord (0,0) through (n,n). The bits are
|
|
in a stream that proceed from column to column and row to row.
|
|
The transformation accomplished by this function changes the bitmap
|
|
into one that has it's bits organized in pages, lines, and columns.
|
|
|
|
Each page is a unit of 8 lines and is organized as follows:
|
|
|
|
---------------------------------------------------------
|
|
|Columns
|
|
---------------------------------------------------------
|
|
| 1| 2| 3| 4| 5| 6| 7| 8| 9|10|11|12|13|14|15|16| ...128
|
|
---------------------------------------------------------
|
|
Line #1 | | | | | | | | | | | | | | | | | ...
|
|
|--------------------------------------------------------
|
|
Line #2 | | | | | | | | | | | | | | | | | ...
|
|
|--------------------------------------------------------
|
|
Line #3 | | | | | | | | | | | | | | | | | ...
|
|
|--------------------------------------------------------
|
|
Line #4 | | | | | | | | | | | | | | | | | ...
|
|
|--------------------------------------------------------
|
|
Line #5 | | | | | | | | | | | | | | | | | ...
|
|
|--------------------------------------------------------
|
|
Line #6 | | | | | | | | | | | | | | | | | ...
|
|
|--------------------------------------------------------
|
|
Line #7 | | | | | | | | | | | | | | | | | ...
|
|
|--------------------------------------------------------
|
|
Line #8 | | | | | | | | | | | | | | | | | ...
|
|
|--------------------------------------------------------
|
|
|
|
The bytes that comprise the bitmap correspond to the columns in the
|
|
page, so there are 128 bytes per page. If the first byte of the
|
|
transformed bitmap is 0x46 then the pixels in column 1 of lines 2,6,&7
|
|
are illuminated by the display.
|
|
|
|
Arguments:
|
|
|
|
Bits - Input bits that are to be transformed
|
|
Width - Width of the bitmap in pixels
|
|
Height - Height of the bitmap in pixels
|
|
NewBits - Buffer to hold the newly transformed bitmap
|
|
|
|
Return Value:
|
|
|
|
NT status code.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG i,j,k,line,idx,mask,coli;
|
|
UCHAR byte;
|
|
ULONG padBytes;
|
|
ULONG byteWidth;
|
|
ULONG NewSize = 0;
|
|
|
|
|
|
//
|
|
// Compute the pad bytes. It is assumed
|
|
// that the data width of the input bitmap
|
|
// is dword aliged long.
|
|
//
|
|
|
|
if (((Width % 32) == 0) || ((Width % 32) > 24)) {
|
|
padBytes = 0;
|
|
} else if ((Width % 32) <= 8) {
|
|
padBytes = 3;
|
|
} else if ((Width % 32) <= 16) {
|
|
padBytes = 2;
|
|
} else {
|
|
padBytes = 1;
|
|
}
|
|
|
|
//
|
|
// Compute the realy byte width
|
|
// based on the pad bytes.
|
|
//
|
|
|
|
byteWidth = (Width / 8) + padBytes;
|
|
if (Width % 8) {
|
|
byteWidth += 1;
|
|
}
|
|
|
|
//
|
|
// Loop through the input bitmap and
|
|
// create a new, morphed bitmap.
|
|
//
|
|
|
|
for (i=0; i<DISPLAY_PAGES; i++) {
|
|
|
|
//
|
|
// starting line number for this page
|
|
//
|
|
line = i * DISPLAY_LINES_PER_PAGE;
|
|
|
|
//
|
|
// This handles the case where the
|
|
// input bitmap is not as tall as the display.
|
|
//
|
|
|
|
if (line >= Height) {
|
|
break;
|
|
}
|
|
|
|
//
|
|
// loop over the bits for this column
|
|
//
|
|
|
|
for (j=0; j<Width; j++) {
|
|
|
|
//
|
|
// Reset the new byte value to a zero state
|
|
//
|
|
|
|
byte = 0;
|
|
|
|
//
|
|
// Compute the column index as the
|
|
// current column number divided by 8 (width of a byte)
|
|
//
|
|
|
|
coli = j >> 3;
|
|
|
|
//
|
|
// Compute the mask that is used to test the
|
|
// bit in the input bitmap.
|
|
//
|
|
|
|
mask = TestMask[j];
|
|
|
|
//
|
|
// Process the bits in all this pages's lines
|
|
// for the current column.
|
|
//
|
|
|
|
for (k=0; k<DISPLAY_LINES_PER_PAGE; k++) {
|
|
|
|
if ((k + line) >= Height) {
|
|
break;
|
|
}
|
|
|
|
//
|
|
// index the byte that contains this pixel
|
|
//
|
|
|
|
idx = (((k + line) * byteWidth)) + coli;
|
|
|
|
//
|
|
// set the bit
|
|
//
|
|
|
|
if (Bits[idx] & mask) {
|
|
byte = byte | (1 << k);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Save the new byte in the bitmap
|
|
//
|
|
|
|
*NewBits = byte;
|
|
NewBits += 1;
|
|
NewSize += 1;
|
|
}
|
|
}
|
|
|
|
return NewSize;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
SaDispWrite(
|
|
IN PVOID DeviceExtensionIn,
|
|
IN PIRP Irp,
|
|
IN PVOID FsContext,
|
|
IN LONGLONG StartingOffset,
|
|
IN PVOID DataBuffer,
|
|
IN ULONG DataBufferLength
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine processes the write request for the local display miniport.
|
|
|
|
Arguments:
|
|
|
|
DeviceExtensionIn - Miniport's device extension
|
|
StartingOffset - Starting offset for the I/O
|
|
DataBuffer - Pointer to the data buffer
|
|
DataBufferLength - Length of the data buffer in bytes
|
|
|
|
Return Value:
|
|
|
|
NT status code.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION) DeviceExtensionIn;
|
|
PSA_DISPLAY_SHOW_MESSAGE SaDisplay = (PSA_DISPLAY_SHOW_MESSAGE)DataBuffer;
|
|
UCHAR i,j;
|
|
PUCHAR NewBits = NULL;
|
|
PUCHAR byte;
|
|
ULONG Pages;
|
|
ULONG NewSize;
|
|
|
|
|
|
UNREFERENCED_PARAMETER(StartingOffset);
|
|
|
|
if (SaDisplay->Width > DISPLAY_WIDTH || SaDisplay->Height > DISPLAY_HEIGHT) {
|
|
REPORT_ERROR( SA_DEVICE_DISPLAY, "Bitmap size is too large\n", STATUS_INVALID_PARAMETER );
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
NewBits = (PUCHAR) SaPortAllocatePool( DeviceExtension, MAX_BITMAP_SIZE );
|
|
if (NewBits == NULL) {
|
|
REPORT_ERROR( SA_DEVICE_DISPLAY, "Failed to allocate pool\n", MAX_BITMAP_SIZE );
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
RtlZeroMemory( NewBits, MAX_BITMAP_SIZE );
|
|
|
|
NewSize = TransformBitmap(
|
|
SaDisplay->Bits,
|
|
SaDisplay->Width,
|
|
SaDisplay->Height,
|
|
NewBits
|
|
);
|
|
if (NewSize == 0) {
|
|
SaPortFreePool( DeviceExtension, NewBits );
|
|
REPORT_ERROR( SA_DEVICE_DISPLAY, "Failed to transform the bitmap\n", STATUS_UNSUCCESSFUL );
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
Pages = SaDisplay->Height / DISPLAY_LINES_PER_PAGE;
|
|
if (SaDisplay->Height % DISPLAY_LINES_PER_PAGE) {
|
|
Pages += 1;
|
|
}
|
|
|
|
for (i=0,byte=NewBits; i<Pages; i++) {
|
|
SetDisplayPage( DeviceExtension->VideoMemBase, i );
|
|
for (j=0; j<SaDisplay->Width; j++) {
|
|
SetDisplayColumnAddress( DeviceExtension->VideoMemBase, j );
|
|
SetDisplayData( DeviceExtension->VideoMemBase, *byte );
|
|
byte += 1;
|
|
}
|
|
}
|
|
|
|
SaPortFreePool( DeviceExtension, NewBits );
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
DriverEntry(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PUNICODE_STRING RegistryPath
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is the driver's entry point, called by the I/O system
|
|
to load the driver. The driver's entry points are initialized and
|
|
a mutex to control paging is initialized.
|
|
|
|
In DBG mode, this routine also examines the registry for special
|
|
debug parameters.
|
|
|
|
Arguments:
|
|
|
|
DriverObject - a pointer to the object that represents this device
|
|
driver.
|
|
|
|
RegistryPath - a pointer to this driver's key in the Services tree.
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
SAPORT_INITIALIZATION_DATA SaPortInitData;
|
|
|
|
|
|
RtlZeroMemory( &SaPortInitData, sizeof(SAPORT_INITIALIZATION_DATA) );
|
|
|
|
SaPortInitData.StructSize = sizeof(SAPORT_INITIALIZATION_DATA);
|
|
SaPortInitData.DeviceType = SA_DEVICE_DISPLAY;
|
|
SaPortInitData.HwInitialize = SaDispHwInitialize;
|
|
SaPortInitData.Write = SaDispWrite;
|
|
SaPortInitData.DeviceIoctl = SaDispDeviceIoctl;
|
|
|
|
SaPortInitData.DeviceExtensionSize = sizeof(DEVICE_EXTENSION);
|
|
|
|
Status = SaPortInitialize( DriverObject, RegistryPath, &SaPortInitData );
|
|
if (!NT_SUCCESS(Status)) {
|
|
REPORT_ERROR( SA_DEVICE_DISPLAY, "SaPortInitialize failed\n", Status );
|
|
return Status;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|