2159 lines
55 KiB
C
2159 lines
55 KiB
C
|
||
|
||
/*++
|
||
|
||
Copyright (c) 1989 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
jxdisp.c
|
||
|
||
Abstract:
|
||
|
||
This module implements the video boot driver for the Jazz system.
|
||
|
||
Author:
|
||
|
||
David M. Robinson (davidro) 24-Jul-1991
|
||
|
||
Environment:
|
||
|
||
Kernel mode.
|
||
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "fwp.h"
|
||
#include "jazzvdeo.h"
|
||
#include "jxvideo.h"
|
||
#include "selfmap.h"
|
||
#include "selftest.h"
|
||
#include "string.h"
|
||
|
||
ARC_STATUS
|
||
InitializeG300 (
|
||
IN PMONITOR_CONFIGURATION_DATA GlobalMonitor
|
||
);
|
||
|
||
ARC_STATUS
|
||
InitializeG364 (
|
||
IN PMONITOR_CONFIGURATION_DATA GlobalMonitor
|
||
);
|
||
|
||
VOID
|
||
FillVideoMemory (
|
||
IN PUCHAR StartAddress,
|
||
IN ULONG SizeInBytes,
|
||
IN ULONG Pattern
|
||
);
|
||
|
||
ARC_STATUS
|
||
DisplayClose (
|
||
IN ULONG FileId
|
||
);
|
||
|
||
ARC_STATUS
|
||
DisplayMount (
|
||
IN PCHAR MountPath,
|
||
IN MOUNT_OPERATION Operation
|
||
);
|
||
|
||
ARC_STATUS
|
||
DisplayOpen (
|
||
IN PCHAR OpenPath,
|
||
IN OPEN_MODE OpenMode,
|
||
IN OUT PULONG FileId
|
||
);
|
||
|
||
ARC_STATUS
|
||
DisplayRead (
|
||
IN ULONG FileId,
|
||
IN PVOID Buffer,
|
||
IN ULONG Length,
|
||
OUT PULONG Count
|
||
);
|
||
|
||
ARC_STATUS
|
||
DisplayGetReadStatus (
|
||
IN ULONG FileId
|
||
);
|
||
|
||
ARC_STATUS
|
||
DisplaySeek (
|
||
IN ULONG FileId,
|
||
IN PLARGE_INTEGER Offset,
|
||
IN SEEK_MODE SeekMode
|
||
);
|
||
|
||
ARC_STATUS
|
||
DisplayWrite (
|
||
IN ULONG FileId,
|
||
IN PVOID Buffer,
|
||
IN ULONG Length,
|
||
OUT PULONG Count
|
||
);
|
||
|
||
ARC_STATUS
|
||
DisplayGetFileInformation (
|
||
IN ULONG FileId,
|
||
OUT PFILE_INFORMATION Finfo
|
||
);
|
||
|
||
VOID FwVideoScroll(
|
||
PVOID StartAddress,
|
||
PVOID EndAddress,
|
||
PVOID Destination
|
||
);
|
||
|
||
#define G300_PALETTE_BLACK 0x000000
|
||
#define G300_PALETTE_RED 0x0000B0
|
||
#define G300_PALETTE_GREEN 0x00B000
|
||
#define G300_PALETTE_YELLOW 0x00B0B0
|
||
#define G300_PALETTE_BLUE 0x900000
|
||
#define G300_PALETTE_MAGENTA 0xB000B0
|
||
#define G300_PALETTE_CYAN 0xB0B000
|
||
#define G300_PALETTE_WHITE 0xB0B0B0
|
||
#define G300_PALETTE_HI_BLACK 0x000000
|
||
#define G300_PALETTE_HI_RED 0x0000FF
|
||
#define G300_PALETTE_HI_GREEN 0x00FF00
|
||
#define G300_PALETTE_HI_YELLOW 0x00FFFF
|
||
#define G300_PALETTE_HI_BLUE 0xFF0000
|
||
#define G300_PALETTE_HI_MAGENTA 0xFF00FF
|
||
#define G300_PALETTE_HI_CYAN 0xFFFF00
|
||
#define G300_PALETTE_HI_WHITE 0xFFFFFF
|
||
|
||
#define G364_PALETTE_BLACK 0x000000
|
||
#define G364_PALETTE_RED 0xB00000
|
||
#define G364_PALETTE_GREEN 0x00B000
|
||
#define G364_PALETTE_YELLOW 0xB0B000
|
||
#define G364_PALETTE_BLUE 0x0000B0
|
||
#define G364_PALETTE_MAGENTA 0xB000B0
|
||
#define G364_PALETTE_CYAN 0x00B0B0
|
||
#define G364_PALETTE_WHITE 0xB0B0B0
|
||
#define G364_PALETTE_HI_BLACK 0x000000
|
||
#define G364_PALETTE_HI_RED 0xFF0000
|
||
#define G364_PALETTE_HI_GREEN 0x00FF00
|
||
#define G364_PALETTE_HI_YELLOW 0xFFFF00
|
||
#define G364_PALETTE_HI_BLUE 0x0000FF
|
||
#define G364_PALETTE_HI_MAGENTA 0xFF00FF
|
||
#define G364_PALETTE_HI_CYAN 0x00FFFF
|
||
#define G364_PALETTE_HI_WHITE 0xFFFFFF
|
||
|
||
//
|
||
// Define virtual address of the video memory and control registers.
|
||
//
|
||
#define VIDEO_MEMORY ((PUCHAR)VIDEO_MEMORY_VIRTUAL_BASE)
|
||
#define VIDEO_CONTROL ((PG300_VIDEO_REGISTERS)VIDEO_CONTROL_VIRTUAL_BASE)
|
||
#define CURSOR_CONTROL ((PCURSOR_REGISTERS)VIDEO_CURSOR_VIRTUAL_BASE)
|
||
|
||
|
||
//
|
||
// Define and initialize device table.
|
||
//
|
||
|
||
BL_DEVICE_ENTRY_TABLE DisplayEntryTable = {
|
||
DisplayClose,
|
||
DisplayMount,
|
||
DisplayOpen,
|
||
DisplayRead,
|
||
DisplayGetReadStatus,
|
||
DisplaySeek,
|
||
DisplayWrite,
|
||
DisplayGetFileInformation,
|
||
(PARC_SET_FILE_INFO_ROUTINE)NULL,
|
||
(PRENAME_ROUTINE)NULL,
|
||
(PARC_GET_DIRECTORY_ENTRY_ROUTINE)NULL
|
||
};
|
||
|
||
//
|
||
// Static data.
|
||
//
|
||
|
||
ARC_DISPLAY_STATUS DisplayStatus;
|
||
BOOLEAN ControlSequence;
|
||
BOOLEAN EscapeSequence;
|
||
BOOLEAN FontSelection;
|
||
ULONG PCount;
|
||
LONG FwColumn;
|
||
LONG FwRow;
|
||
BOOLEAN FwHighIntensity;
|
||
BOOLEAN FwUnderscored;
|
||
BOOLEAN FwReverseVideo;
|
||
ULONG FwForegroundColor;
|
||
ULONG FwBackgroundColor;
|
||
PCHAR DisplayDevicePath = "multi(0)video(0)monitor(0)";
|
||
ULONG DisplayWidth;
|
||
ULONG DisplayText;
|
||
ULONG FrameSize;
|
||
ULONG ScrollLine;
|
||
ULONG ScrollLength;
|
||
LONG MaxRow;
|
||
LONG MaxColumn;
|
||
ULONG CharacterHeight;
|
||
ULONG CharacterWidth;
|
||
ULONG CharacterSize;
|
||
PCHAR FwFont;
|
||
ULONG FontIncrement;
|
||
ULONG ColorTable[16] = { 0x00000000,
|
||
0x0000000f,
|
||
0x00000f00,
|
||
0x00000f0f,
|
||
0x000f0000,
|
||
0x000f000f,
|
||
0x000f0f00,
|
||
0x000f0f0f,
|
||
0x0f000000,
|
||
0x0f00000f,
|
||
0x0f000f00,
|
||
0x0f000f0f,
|
||
0x0f0f0000,
|
||
0x0f0f000f,
|
||
0x0f0f0f00,
|
||
0x0f0f0f0f };
|
||
|
||
#define CONTROL_SEQUENCE_MAX_PARAMETER 10
|
||
LONG Parameter[CONTROL_SEQUENCE_MAX_PARAMETER];
|
||
MONITOR_CONFIGURATION_DATA MonitorData;
|
||
extern PUCHAR IdentifierString;
|
||
|
||
MONITOR_CONFIGURATION_DATA DefaultMonitor = {
|
||
0, // version : do not change
|
||
0, // revision : do not change
|
||
1280, // HorizontalResolution
|
||
11832, // HorizontalDisplayTime
|
||
1596, // HorizontalBackPorch
|
||
587, // HorizontalFrontPorch
|
||
1745, // HorizontalSync
|
||
1024, // VerticalResolution
|
||
28, // VerticalBackPorch
|
||
1, // VerticalFrontPorch
|
||
3, // VerticalSync
|
||
0, // HorizontalScreenSize : do not change
|
||
0 // VerticalScreenSize : do not change
|
||
};
|
||
|
||
|
||
#define FW_INVALID_CHARACTER 0xb1
|
||
|
||
UCHAR LdUnicodeToAscii[128] = { 0xc4,0xb1,0xb3,0xb1,0xb1,0xb1,0xb1,0xb1,
|
||
0xb1,0xb1,0xb1,0xb1,0xda,0xb1,0xb1,0xb1,
|
||
0xbf,0xb1,0xb1,0xb1,0xc0,0xb1,0xb1,0xb1,
|
||
0xd9,0xb1,0xb1,0xb1,0xc3,0xb1,0xb1,0xb1,
|
||
0xb1,0xb1,0xb1,0xb1,0xb4,0xb1,0xb1,0xb1,
|
||
0xb1,0xb1,0xb1,0xb1,0xc2,0xb1,0xb1,0xb1,
|
||
0xb1,0xb1,0xb1,0xb1,0xc1,0xb1,0xb1,0xb1,
|
||
0xb1,0xb1,0xb1,0xb1,0xc5,0xb1,0xb1,0xb1,
|
||
0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,
|
||
0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,
|
||
0xcd,0xba,0xd5,0xd6,0xc9,0xb8,0xb7,0xbb,
|
||
0xd4,0xd3,0xc8,0xbe,0xbd,0xbc,0xc6,0xc7,
|
||
0xcc,0xb5,0xb6,0xb9,0xd1,0xd2,0xcb,0xcf,
|
||
0xd0,0xca,0xd8,0xd7,0xce,0xb1,0xb1,0xb1,
|
||
0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,
|
||
0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1 };
|
||
|
||
|
||
//
|
||
// Declare externally defined data.
|
||
//
|
||
|
||
extern UCHAR FwFont10x20[1];
|
||
extern UCHAR FwFont8x12[1];
|
||
|
||
|
||
//
|
||
// Define routine prototypes.
|
||
//
|
||
|
||
VOID
|
||
FwDisplayCharacter(
|
||
IN UCHAR Character
|
||
);
|
||
|
||
VOID
|
||
FwSetAllAttributes(
|
||
VOID
|
||
);
|
||
|
||
|
||
ARC_STATUS
|
||
DisplayGetFileInformation (
|
||
IN ULONG FileId,
|
||
OUT PFILE_INFORMATION Finfo
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function returns EINVAL as no FileInformation can be
|
||
returned for the Display driver.
|
||
|
||
Arguments:
|
||
|
||
The arguments are not used.
|
||
|
||
Return Value:
|
||
|
||
EINVAL is returned
|
||
|
||
--*/
|
||
|
||
{
|
||
return EINVAL;
|
||
}
|
||
|
||
ARC_STATUS
|
||
DisplayClose (
|
||
IN ULONG FileId
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function closes the file table entry specified by the file id.
|
||
|
||
Arguments:
|
||
|
||
FileId - Supplies the file table index.
|
||
|
||
Return Value:
|
||
|
||
ESUCCESS is returned
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
BlFileTable[FileId].Flags.Open = 0;
|
||
return ESUCCESS;
|
||
}
|
||
|
||
ARC_STATUS
|
||
DisplayMount (
|
||
IN PCHAR MountPath,
|
||
IN MOUNT_OPERATION Operation
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
|
||
Arguments:
|
||
|
||
|
||
Return Value:
|
||
|
||
|
||
--*/
|
||
|
||
{
|
||
return EINVAL;
|
||
}
|
||
|
||
ARC_STATUS
|
||
DisplayOpen (
|
||
IN PCHAR OpenPath,
|
||
IN OPEN_MODE OpenMode,
|
||
IN OUT PULONG FileId
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This is the open routine for the display device.
|
||
|
||
Arguments:
|
||
|
||
OpenPath - Supplies the pathname of the device to open.
|
||
|
||
OpenMode - Supplies the mode (read only, write only, or read write).
|
||
|
||
FileId - Supplies a free file identifier to use. If the device is already
|
||
open this parameter can be used to return the file identifier
|
||
already in use.
|
||
|
||
Return Value:
|
||
|
||
If the open was successful, ESUCCESS is returned, otherwise an error code
|
||
is returned.
|
||
|
||
--*/
|
||
{
|
||
PCONSOLE_CONTEXT Context;
|
||
|
||
Context = &BlFileTable[*FileId].u.ConsoleContext;
|
||
if ( strstr(OpenPath, ")console(1)" ) != NULL ) {
|
||
Context->ConsoleNumber = 1;
|
||
} else {
|
||
Context->ConsoleNumber = 0;
|
||
}
|
||
|
||
return ESUCCESS;
|
||
}
|
||
|
||
ARC_STATUS
|
||
DisplayRead (
|
||
IN ULONG FileId,
|
||
IN PVOID Buffer,
|
||
IN ULONG Length,
|
||
OUT PULONG Count
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
|
||
--*/
|
||
{
|
||
return(ESUCCESS);
|
||
}
|
||
|
||
|
||
ARC_STATUS
|
||
DisplayGetReadStatus (
|
||
IN ULONG FileId
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
|
||
--*/
|
||
{
|
||
return ESUCCESS;
|
||
}
|
||
|
||
|
||
ARC_STATUS
|
||
DisplayWrite (
|
||
IN ULONG FileId,
|
||
IN PVOID Buffer,
|
||
IN ULONG Length,
|
||
OUT PULONG Count
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This module implements the ARC firmware Console Output functions as
|
||
described in the Advanced Risc Computing Specification (Revision 1.00),
|
||
section 3.3.1.5.1 Basic Character Console, and section 3.3.1.5.2 Enhanced
|
||
Character Console for a MIPS R3000 or R4000 Jazz system.
|
||
|
||
|
||
Arguments:
|
||
|
||
FileId - Supplies a file id.
|
||
|
||
Buffer - Supplies a pointer to a buffer containing the characters to
|
||
be displayed.
|
||
|
||
Length - Supplies the length of Buffer.
|
||
|
||
Count - Returns the count of the characters that were displayed.
|
||
|
||
Return Value:
|
||
|
||
If the characters were successfully displayed, ESUCCESS is returned,
|
||
otherwise one of the following error codes is returned.
|
||
|
||
EBADF The file descriptor specified by FileId is invalid.
|
||
|
||
EIO An output error occurred.
|
||
|
||
--*/
|
||
|
||
{
|
||
PCONSOLE_CONTEXT Context;
|
||
ARC_STATUS Status;
|
||
PUCHAR String;
|
||
LONG ColumnEndPoint;
|
||
ULONG Index, Index2;
|
||
ULONG FGColor;
|
||
ULONG BGColor;
|
||
BOOLEAN Unicode;
|
||
|
||
Context = &BlFileTable[FileId].u.ConsoleContext;
|
||
if ( Context->ConsoleNumber == 1) {
|
||
if (Length & 1) {
|
||
|
||
//
|
||
// Length is not an even number of bytes, return an error.
|
||
//
|
||
|
||
return(EINVAL);
|
||
}
|
||
Unicode = TRUE;
|
||
} else {
|
||
Unicode = FALSE;
|
||
}
|
||
|
||
//
|
||
// Process each character in turn.
|
||
//
|
||
|
||
Status = ESUCCESS;
|
||
String = (PUCHAR)Buffer;
|
||
|
||
for ( *Count = 0 ;
|
||
*Count < Length ;
|
||
(*Count)++, String++ ) {
|
||
|
||
//
|
||
// Check for Unicode character.
|
||
//
|
||
|
||
if (Unicode) {
|
||
if (*Count & 1) {
|
||
|
||
//
|
||
// Skip the upper half of each character.
|
||
//
|
||
|
||
continue;
|
||
} else {
|
||
if (*(String + 1) == 0x25) {
|
||
|
||
//
|
||
// If a Unicode line drawing character, go ahead and display
|
||
// it.
|
||
//
|
||
|
||
if (*String <= 0x7f) {
|
||
FwDisplayCharacter(LdUnicodeToAscii[*String]);
|
||
} else {
|
||
FwDisplayCharacter(FW_INVALID_CHARACTER);
|
||
}
|
||
|
||
if (FwColumn < MaxColumn) {
|
||
FwColumn++;
|
||
}
|
||
continue;
|
||
} else {
|
||
if (*(String + 1) != 0) {
|
||
|
||
//
|
||
// Display an invalid character.
|
||
//
|
||
|
||
FwDisplayCharacter(FW_INVALID_CHARACTER);
|
||
|
||
if (FwColumn < MaxColumn) {
|
||
FwColumn++;
|
||
}
|
||
continue;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
//
|
||
// If we're in the middle of a control sequence, continue scanning,
|
||
// otherwise process character.
|
||
//
|
||
|
||
if (ControlSequence) {
|
||
|
||
//
|
||
// If the character is a digit, update parameter value.
|
||
//
|
||
|
||
if ((*String >= '0') && (*String <= '9')) {
|
||
Parameter[PCount] = Parameter[PCount] * 10 + *String - '0';
|
||
continue;
|
||
}
|
||
|
||
//
|
||
// If we are in the middle of a font selection sequence, this
|
||
// character must be a 'D', otherwise reset control sequence.
|
||
//
|
||
|
||
if (FontSelection) {
|
||
|
||
//if (*String == 'D') {
|
||
//
|
||
// //
|
||
// // Other fonts not implemented yet.
|
||
// //
|
||
//
|
||
//} else {
|
||
//}
|
||
|
||
ControlSequence = FALSE;
|
||
FontSelection = FALSE;
|
||
continue;
|
||
}
|
||
|
||
switch (*String) {
|
||
|
||
//
|
||
// If a semicolon, move to the next parameter.
|
||
//
|
||
|
||
case ';':
|
||
|
||
PCount++;
|
||
if (PCount > CONTROL_SEQUENCE_MAX_PARAMETER) {
|
||
PCount = CONTROL_SEQUENCE_MAX_PARAMETER;
|
||
}
|
||
Parameter[PCount] = 0;
|
||
break;
|
||
|
||
//
|
||
// If a 'J', erase part or all of the screen.
|
||
//
|
||
|
||
case 'J':
|
||
|
||
switch (Parameter[0]) {
|
||
|
||
//
|
||
// Erase to end of the screen.
|
||
//
|
||
|
||
case 0:
|
||
//
|
||
// Clear to end of line by Writing char ' '
|
||
//
|
||
ColumnEndPoint = FwColumn;
|
||
while (FwColumn <= MaxColumn) {
|
||
FwDisplayCharacter(' ');
|
||
FwColumn++;
|
||
}
|
||
FwColumn = ColumnEndPoint;
|
||
if (FwRow+1 < MaxRow) {
|
||
//
|
||
// Zero the rest of the screen
|
||
//
|
||
FillVideoMemory((PUCHAR)(VIDEO_MEMORY + ((FwRow+1) * ScrollLine)),
|
||
FrameSize - ((FwRow+1) * ScrollLine),
|
||
FwBackgroundColor
|
||
);
|
||
}
|
||
break;
|
||
|
||
//
|
||
// Erase from the beginning of the screen.
|
||
//
|
||
|
||
case 1:
|
||
if (FwRow) {
|
||
FillVideoMemory((PUCHAR)(VIDEO_MEMORY),
|
||
(FwRow * ScrollLine),
|
||
FwBackgroundColor
|
||
);
|
||
}
|
||
ColumnEndPoint=FwColumn;
|
||
for (FwColumn=0; FwColumn < ColumnEndPoint; FwColumn++) {
|
||
FwDisplayCharacter(' ');
|
||
}
|
||
break;
|
||
|
||
//
|
||
// Erase entire screen.
|
||
//
|
||
|
||
default :
|
||
FillVideoMemory(VIDEO_MEMORY,
|
||
FrameSize,
|
||
FwBackgroundColor);
|
||
FwRow = 0;
|
||
FwColumn = 0;
|
||
break;
|
||
}
|
||
|
||
ControlSequence = FALSE;
|
||
break;
|
||
|
||
//
|
||
// If a 'K', erase part or all of the line.
|
||
//
|
||
|
||
case 'K':
|
||
|
||
switch (Parameter[0]) {
|
||
|
||
//
|
||
// Erase to end of the line.
|
||
//
|
||
|
||
case 0:
|
||
ColumnEndPoint = FwColumn;
|
||
FwColumn = MaxColumn + 1;
|
||
do {
|
||
FwColumn--;
|
||
FwDisplayCharacter(' ');
|
||
} while (FwColumn != ColumnEndPoint);
|
||
break;
|
||
|
||
//
|
||
// Erase from the beginning of the line.
|
||
//
|
||
|
||
case 1:
|
||
ColumnEndPoint = FwColumn;
|
||
FwColumn = -1;
|
||
do {
|
||
FwColumn++;
|
||
FwDisplayCharacter(' ');
|
||
} while (FwColumn != ColumnEndPoint);
|
||
break;
|
||
|
||
//
|
||
// Erase entire line.
|
||
//
|
||
|
||
default :
|
||
FwColumn = MaxColumn + 1;
|
||
do {
|
||
FwColumn--;
|
||
FwDisplayCharacter(' ');
|
||
} while (FwColumn != 0);
|
||
break;
|
||
}
|
||
|
||
ControlSequence = FALSE;
|
||
break;
|
||
|
||
//
|
||
// If a 'H', move cursor to position.
|
||
//
|
||
|
||
case 'H':
|
||
|
||
//
|
||
// Shift parameters to be 1 based.
|
||
//
|
||
|
||
if (Parameter[0] != 0) {
|
||
Parameter[0] -= 1;
|
||
}
|
||
if (Parameter[1] != 0) {
|
||
Parameter[1] -= 1;
|
||
}
|
||
|
||
FwRow = Parameter[0];
|
||
if (FwRow > MaxRow) {
|
||
FwRow = MaxRow;
|
||
}
|
||
FwColumn = Parameter[1];
|
||
if (FwColumn > MaxColumn) {
|
||
FwColumn = MaxColumn;
|
||
}
|
||
|
||
ControlSequence = FALSE;
|
||
break;
|
||
|
||
//
|
||
// If a 'A', move cursor up.
|
||
//
|
||
|
||
case 'A':
|
||
|
||
//
|
||
// A parameter of zero still means a cursor shift position of 1.
|
||
//
|
||
|
||
if (Parameter[0] == 0) {
|
||
Parameter[0] = 1;
|
||
}
|
||
|
||
if (Parameter[0] > FwRow) {
|
||
FwRow = 0;
|
||
} else {
|
||
FwRow -= Parameter[0];
|
||
}
|
||
ControlSequence = FALSE;
|
||
break;
|
||
|
||
//
|
||
// If a 'B', move cursor down.
|
||
//
|
||
|
||
case 'B':
|
||
|
||
//
|
||
// A parameter of zero still means a cursor shift position of 1.
|
||
//
|
||
|
||
if (Parameter[0] == 0) {
|
||
Parameter[0] = 1;
|
||
}
|
||
|
||
if (Parameter[0] + FwRow > MaxRow) {
|
||
FwRow = MaxRow;
|
||
} else {
|
||
FwRow += Parameter[0];
|
||
}
|
||
ControlSequence = FALSE;
|
||
break;
|
||
|
||
//
|
||
// If a 'C', move cursor right.
|
||
//
|
||
|
||
case 'C':
|
||
|
||
//
|
||
// A parameter of zero still means a cursor shift position of 1.
|
||
//
|
||
|
||
if (Parameter[0] == 0) {
|
||
Parameter[0] = 1;
|
||
}
|
||
|
||
if (Parameter[0] + FwColumn > MaxColumn) {
|
||
FwColumn = MaxColumn;
|
||
} else {
|
||
FwColumn += Parameter[0];
|
||
}
|
||
ControlSequence = FALSE;
|
||
break;
|
||
|
||
//
|
||
// If a 'D', move cursor left.
|
||
//
|
||
|
||
case 'D':
|
||
|
||
//
|
||
// A parameter of zero still means a cursor shift position of 1.
|
||
//
|
||
|
||
if (Parameter[0] == 0) {
|
||
Parameter[0] = 1;
|
||
}
|
||
|
||
if (Parameter[0] > FwColumn) {
|
||
FwColumn = 0;
|
||
} else {
|
||
FwColumn -= Parameter[0];
|
||
}
|
||
ControlSequence = FALSE;
|
||
break;
|
||
|
||
//
|
||
// If a ' ', could be a FNT selection command.
|
||
//
|
||
|
||
case ' ':
|
||
FontSelection = TRUE;
|
||
break;
|
||
|
||
//
|
||
// If a 'm', Select Graphics Rendition command.
|
||
//
|
||
|
||
case 'm':
|
||
|
||
//
|
||
// Select action based on each parameter.
|
||
//
|
||
|
||
for ( Index = 0 ; Index <= PCount ; Index++ ) {
|
||
switch (Parameter[Index]) {
|
||
|
||
//
|
||
// Attributes off.
|
||
//
|
||
|
||
case 0:
|
||
FwHighIntensity = FALSE;
|
||
FwUnderscored = FALSE;
|
||
FwReverseVideo = FALSE;
|
||
break;
|
||
|
||
//
|
||
// High Intensity.
|
||
//
|
||
|
||
case 1:
|
||
FwHighIntensity = TRUE;
|
||
break;
|
||
|
||
//
|
||
// Underscored.
|
||
//
|
||
|
||
case 4:
|
||
FwUnderscored = TRUE;
|
||
break;
|
||
|
||
//
|
||
// Reverse Video.
|
||
//
|
||
|
||
case 7:
|
||
FwReverseVideo = TRUE;
|
||
break;
|
||
|
||
//
|
||
// Font selection, not implemented yet.
|
||
//
|
||
|
||
case 10:
|
||
case 11:
|
||
case 12:
|
||
case 13:
|
||
case 14:
|
||
case 15:
|
||
case 16:
|
||
case 17:
|
||
case 18:
|
||
case 19:
|
||
break;
|
||
|
||
//
|
||
// Foreground Color.
|
||
//
|
||
|
||
case 30:
|
||
case 31:
|
||
case 32:
|
||
case 33:
|
||
case 34:
|
||
case 35:
|
||
case 36:
|
||
case 37:
|
||
FwForegroundColor = Parameter[Index] - 30;
|
||
break;
|
||
|
||
//
|
||
// Background Color.
|
||
//
|
||
|
||
case 40:
|
||
case 41:
|
||
case 42:
|
||
case 43:
|
||
case 44:
|
||
case 45:
|
||
case 46:
|
||
case 47:
|
||
FwBackgroundColor = Parameter[Index] - 40;
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Recompute color table.
|
||
//
|
||
|
||
if (FwReverseVideo) {
|
||
FGColor = FwBackgroundColor;
|
||
BGColor = FwForegroundColor + (FwHighIntensity ? 0x08 : 0 );
|
||
} else {
|
||
FGColor = FwForegroundColor + (FwHighIntensity ? 0x08 : 0 );
|
||
BGColor = FwBackgroundColor;
|
||
}
|
||
|
||
for ( Index2 = 0 ; Index2 < 16 ; Index2++ ) {
|
||
ColorTable[Index2] = ((Index2 & 8) ? FGColor : BGColor ) << 24 |
|
||
((Index2 & 4) ? FGColor : BGColor ) << 16 |
|
||
((Index2 & 2) ? FGColor : BGColor ) << 8 |
|
||
((Index2 & 1) ? FGColor : BGColor ) ;
|
||
}
|
||
|
||
ControlSequence = FALSE;
|
||
FwSetAllAttributes();
|
||
break;
|
||
|
||
default:
|
||
ControlSequence = FALSE;
|
||
break;
|
||
}
|
||
|
||
//
|
||
// This is not a control sequence, check for escape sequence
|
||
//
|
||
|
||
} else {
|
||
|
||
//
|
||
// If escape sequence, check for control sequence, otherwise
|
||
// process single character.
|
||
//
|
||
|
||
if (EscapeSequence) {
|
||
//
|
||
// Check for '[', means control sequence, any other following
|
||
// character is ignored.
|
||
//
|
||
|
||
if (*String == '[') {
|
||
|
||
ControlSequence = TRUE;
|
||
|
||
//
|
||
// Initialize first parameter.
|
||
//
|
||
|
||
PCount = 0;
|
||
Parameter[0] = 0;
|
||
}
|
||
EscapeSequence = FALSE;
|
||
|
||
//
|
||
// This is not a control or escape sequence, process single character.
|
||
//
|
||
|
||
} else {
|
||
|
||
//
|
||
// Check for special characters.
|
||
//
|
||
|
||
switch (*String) {
|
||
|
||
//
|
||
// Control sequence.
|
||
//
|
||
|
||
case ASCII_CSI:
|
||
ControlSequence = TRUE;
|
||
|
||
//
|
||
// Initialize first parameter.
|
||
//
|
||
|
||
PCount = 0;
|
||
Parameter[0] = 0;
|
||
break;
|
||
|
||
//
|
||
// Check for escape sequence.
|
||
//
|
||
|
||
case ASCII_ESC:
|
||
EscapeSequence = TRUE;
|
||
break;
|
||
|
||
//
|
||
// Vertical tab/Form feed Line feed.
|
||
//
|
||
|
||
case ASCII_LF:
|
||
case ASCII_VT:
|
||
case ASCII_FF:
|
||
if (FwRow == MaxRow) {
|
||
VenScrollVideo();
|
||
} else {
|
||
FwRow++;
|
||
}
|
||
|
||
break;
|
||
|
||
//
|
||
// Carriage return.
|
||
//
|
||
|
||
case ASCII_CR:
|
||
FwColumn = 0;
|
||
break;
|
||
|
||
//
|
||
// NUL, no action.
|
||
//
|
||
|
||
case ASCII_NUL:
|
||
break;
|
||
|
||
//
|
||
// Ring bell, not implemented yet.
|
||
//
|
||
|
||
case ASCII_BEL:
|
||
break;
|
||
|
||
//
|
||
// Backspace.
|
||
//
|
||
|
||
case ASCII_BS:
|
||
if (FwColumn != 0) {
|
||
FwColumn--;
|
||
}
|
||
break;
|
||
|
||
//
|
||
// Horizontal tab.
|
||
//
|
||
|
||
case ASCII_HT:
|
||
FwColumn = ((FwColumn / 8) + 1) * 8;
|
||
if (FwColumn > MaxColumn) {
|
||
FwColumn = MaxColumn;
|
||
}
|
||
break;
|
||
default:
|
||
FwDisplayCharacter(*String);
|
||
if (FwColumn < MaxColumn) {
|
||
FwColumn++;
|
||
}
|
||
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return Status;
|
||
}
|
||
|
||
ARC_STATUS
|
||
DisplaySeek (
|
||
IN ULONG FileId,
|
||
IN PLARGE_INTEGER Offset,
|
||
IN SEEK_MODE SeekMode
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
|
||
ESUCCESS is returned.
|
||
|
||
--*/
|
||
|
||
{
|
||
return ESUCCESS;
|
||
}
|
||
|
||
ARC_STATUS
|
||
DisplayBootInitialize (
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine initializes the video control registers, and clears the
|
||
video screen.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
If the video was initialized, ESUCCESS is returned, otherwise an error
|
||
code is returned.
|
||
|
||
--*/
|
||
|
||
{
|
||
ARC_STATUS Status;
|
||
JAZZ_VIDEO_TYPE VideoType;
|
||
|
||
//
|
||
// Initialize the firmware routines.
|
||
//
|
||
|
||
(PARC_TEST_UNICODE_CHARACTER_ROUTINE)SYSTEM_BLOCK->FirmwareVector[TestUnicodeCharacterRoutine] =
|
||
FwTestUnicodeCharacter;
|
||
|
||
(PARC_GET_DISPLAY_STATUS_ROUTINE)SYSTEM_BLOCK->FirmwareVector[GetDisplayStatusRoutine] =
|
||
FwGetDisplayStatus;
|
||
|
||
|
||
|
||
//
|
||
// Initialize the vendor routines that might be changed by the video prom.
|
||
//
|
||
|
||
(PVEN_SET_DISPLAY_ATTRIBUTES_ROUTINE)SYSTEM_BLOCK->VendorVector[SetDisplayAttributesRoutine] =
|
||
FwSetDisplayAttributes;
|
||
|
||
(PVEN_OUTPUT_CHARACTER_ROUTINE)SYSTEM_BLOCK->VendorVector[OutputCharacterRoutine] =
|
||
FwOutputCharacter;
|
||
|
||
(PVEN_SCROLL_VIDEO_ROUTINE)SYSTEM_BLOCK->VendorVector[ScrollVideoRoutine] =
|
||
FwScrollVideo;
|
||
|
||
//
|
||
// Get the monitor configuration data.
|
||
//
|
||
|
||
FwGetVideoData(&MonitorData);
|
||
|
||
//
|
||
// Try to initialize G300.
|
||
//
|
||
|
||
Status = ESUCCESS;
|
||
if (InitializeG300(&MonitorData) == ESUCCESS) {
|
||
IdentifierString = "Jazz G300";
|
||
} else {
|
||
|
||
//
|
||
// G300 did not initialize properly, try a video PROM.
|
||
//
|
||
|
||
if (InitializeVideoFromProm(&MonitorData) == ESUCCESS) {
|
||
} else {
|
||
|
||
//
|
||
// There is no valid video PROM, try for a G364 without a video
|
||
// PROM.
|
||
//
|
||
|
||
if (InitializeG364(&MonitorData) == ESUCCESS) {
|
||
|
||
//
|
||
// Determine which G364 video board is installed.
|
||
//
|
||
|
||
VideoType = READ_REGISTER_UCHAR((PUCHAR)0xe0200000);
|
||
|
||
switch (VideoType) {
|
||
case JazzVideoG364:
|
||
IdentifierString = "Jazz G364";
|
||
break;
|
||
case MipsVideoG364:
|
||
IdentifierString = "Mips G364";
|
||
break;
|
||
default:
|
||
IdentifierString = "Unknown";
|
||
break;
|
||
}
|
||
|
||
} else {
|
||
|
||
//
|
||
// No valid video initialization was found.
|
||
//
|
||
|
||
Status = EINVAL;
|
||
IdentifierString = "Unknown";
|
||
}
|
||
}
|
||
}
|
||
|
||
//
|
||
// Initialize static data.
|
||
//
|
||
|
||
ControlSequence = FALSE;
|
||
EscapeSequence = FALSE;
|
||
FontSelection = FALSE;
|
||
FwColumn = 0;
|
||
FwRow = 0;
|
||
FwHighIntensity = FALSE;
|
||
FwUnderscored = FALSE;
|
||
FwReverseVideo = FALSE;
|
||
|
||
//
|
||
// Initialize static data.
|
||
//
|
||
|
||
FwForegroundColor = FW_COLOR_HI_WHITE;
|
||
FwBackgroundColor = FW_COLOR_BLACK;
|
||
DisplayWidth = MonitorData.HorizontalResolution;
|
||
FrameSize = (DisplayWidth * MonitorData.VerticalResolution);
|
||
|
||
if (DisplayWidth >= 800) {
|
||
CharacterWidth = 10;
|
||
CharacterHeight = 20;
|
||
FwFont = FwFont10x20;
|
||
FontIncrement = (DisplayWidth - CharacterWidth) / sizeof(USHORT);
|
||
} else {
|
||
CharacterWidth = 8;
|
||
CharacterHeight = 12;
|
||
FwFont = FwFont8x12;
|
||
FontIncrement = (DisplayWidth - CharacterWidth) / sizeof(ULONG);
|
||
}
|
||
CharacterSize = (CharacterHeight * ((CharacterWidth+7) / 8));
|
||
|
||
ScrollLine = (DisplayWidth * CharacterHeight);
|
||
ScrollLength = (ScrollLine * ((MonitorData.VerticalResolution / CharacterHeight) - 1));
|
||
MaxRow = ((MonitorData.VerticalResolution / CharacterHeight) - 1);
|
||
MaxColumn = ((DisplayWidth / CharacterWidth) - 1);
|
||
|
||
//
|
||
// Initialize the console context value for the display output so writes
|
||
// to the screen will work before the console is opened.
|
||
//
|
||
|
||
BlFileTable[ARC_CONSOLE_OUTPUT].u.ConsoleContext.ConsoleNumber = 0;
|
||
|
||
FillVideoMemory(VIDEO_MEMORY,FrameSize,FwBackgroundColor);
|
||
|
||
//
|
||
// Initialize the attributes.
|
||
//
|
||
|
||
FwSetAllAttributes();
|
||
|
||
return Status;
|
||
}
|
||
|
||
|
||
|
||
ARC_STATUS
|
||
InitializeG300 (
|
||
IN OUT PMONITOR_CONFIGURATION_DATA GlobalMonitor
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine initializes the G300 video control registers, and clears the
|
||
video screen.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
If the video was initialized, ESUCCESS is returned, otherwise an error
|
||
code is returned.
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONG ScreenUnitRate;
|
||
ULONG MultiplierValue;
|
||
ULONG HalfLineTime;
|
||
ULONG FrontPorch;
|
||
ULONG ShortDisplay;
|
||
ULONG BackPorch;
|
||
ULONG HalfSync;
|
||
ULONG TransferDelay;
|
||
ULONG DmaDisplay;
|
||
ULONG DataLong;
|
||
ULONG i;
|
||
PG300_VIDEO_REGISTERS VideoControl = VIDEO_CONTROL;
|
||
PCURSOR_REGISTERS CursorControl = CURSOR_CONTROL;
|
||
PMONITOR_CONFIGURATION_DATA CurrentMonitor;
|
||
BOOLEAN UpdateMonitor;
|
||
|
||
CurrentMonitor = GlobalMonitor;
|
||
UpdateMonitor = FALSE;
|
||
|
||
//
|
||
// Check to see if the Monitor parameters are valid.
|
||
//
|
||
|
||
do {
|
||
|
||
//
|
||
// Determine the desired screen unit rate, in picoseconds (a screen unit is
|
||
// four pixels).
|
||
//
|
||
|
||
if ((CurrentMonitor->HorizontalDisplayTime != 0) && (CurrentMonitor->HorizontalResolution != 0)) {
|
||
ScreenUnitRate = (CurrentMonitor->HorizontalDisplayTime * 1000) * 4 / CurrentMonitor->HorizontalResolution;
|
||
} else {
|
||
continue;
|
||
}
|
||
|
||
if (ScreenUnitRate == 0) {
|
||
continue;
|
||
}
|
||
|
||
//
|
||
// Multiplier value is the oscillator period (in picoseconds) divided by
|
||
// the pixel rate.
|
||
//
|
||
|
||
MultiplierValue = 123077 / (ScreenUnitRate / 4);
|
||
|
||
if (MultiplierValue < 5 || MultiplierValue > 18) {
|
||
continue;
|
||
}
|
||
|
||
break;
|
||
|
||
//
|
||
// If the while is executed, the parameters are not valid. Set UpdateMonitor
|
||
// and point to the default parameters, which are valid. Note that the
|
||
// "while" will evaluate TRUE because the value of (a,b) is the value of b.
|
||
//
|
||
|
||
} while (CurrentMonitor = &DefaultMonitor, UpdateMonitor = TRUE);
|
||
|
||
//
|
||
// Initialize the G300B boot register value.
|
||
//
|
||
|
||
DataLong = 0;
|
||
((PG300_VIDEO_BOOT)(&DataLong))->Multiplier = MultiplierValue;
|
||
((PG300_VIDEO_BOOT)(&DataLong))->ClockSelect = 1;
|
||
WRITE_REGISTER_ULONG(&VideoControl->Boot.Long, DataLong);
|
||
|
||
//
|
||
// Wait a few cycles until the pll stabilizes.
|
||
//
|
||
|
||
FwStallExecution(200);
|
||
|
||
//
|
||
// Disable the G300B display controller.
|
||
//
|
||
|
||
DataLong = 0;
|
||
((PG300_VIDEO_PARAMETERS)(&DataLong))->PlainWave = 1;
|
||
WRITE_REGISTER_ULONG(&VideoControl->Parameters.Long, DataLong);
|
||
|
||
//
|
||
// Determine if this is actually the G300 board.
|
||
//
|
||
|
||
WRITE_REGISTER_UCHAR((PUCHAR)0xe0200000,0);
|
||
if (READ_REGISTER_UCHAR((PUCHAR)0xe0200000) != JazzVideoG300) {
|
||
return ENODEV;
|
||
}
|
||
|
||
//
|
||
// Update the monitor parameters if necessary.
|
||
//
|
||
|
||
if (UpdateMonitor) {
|
||
GlobalMonitor->HorizontalResolution = DefaultMonitor.HorizontalResolution;
|
||
GlobalMonitor->HorizontalDisplayTime = DefaultMonitor.HorizontalDisplayTime;
|
||
GlobalMonitor->HorizontalBackPorch = DefaultMonitor.HorizontalBackPorch;
|
||
GlobalMonitor->HorizontalFrontPorch = DefaultMonitor.HorizontalFrontPorch;
|
||
GlobalMonitor->HorizontalSync = DefaultMonitor.HorizontalSync;
|
||
GlobalMonitor->VerticalResolution = DefaultMonitor.VerticalResolution;
|
||
GlobalMonitor->VerticalBackPorch = DefaultMonitor.VerticalBackPorch;
|
||
GlobalMonitor->VerticalFrontPorch = DefaultMonitor.VerticalFrontPorch;
|
||
GlobalMonitor->VerticalSync = DefaultMonitor.VerticalSync;
|
||
}
|
||
|
||
//
|
||
// Initialize the G300B operational values.
|
||
//
|
||
|
||
HalfSync = (CurrentMonitor->HorizontalSync * 1000) / ScreenUnitRate / 2;
|
||
WRITE_REGISTER_ULONG(&VideoControl->HorizonalSync.Long, HalfSync );
|
||
|
||
BackPorch = (CurrentMonitor->HorizontalBackPorch * 1000) / ScreenUnitRate;
|
||
WRITE_REGISTER_ULONG(&VideoControl->BackPorch.Long, BackPorch );
|
||
|
||
WRITE_REGISTER_ULONG(&VideoControl->Display.Long, CurrentMonitor->HorizontalResolution / 4);
|
||
|
||
//
|
||
// The LineTime needs to be an even number of units, so calculate LineTime / 2
|
||
// and then multiply by two to program. ShortDisplay and BroadPulse also
|
||
// use LineTime / 2.
|
||
//
|
||
|
||
HalfLineTime = (CurrentMonitor->HorizontalSync + CurrentMonitor->HorizontalFrontPorch +
|
||
CurrentMonitor->HorizontalBackPorch + CurrentMonitor->HorizontalDisplayTime) * 1000 /
|
||
ScreenUnitRate / 2;
|
||
|
||
WRITE_REGISTER_ULONG(&VideoControl->LineTime.Long, HalfLineTime * 2);
|
||
|
||
FrontPorch = (CurrentMonitor->HorizontalFrontPorch * 1000) / ScreenUnitRate;
|
||
ShortDisplay = HalfLineTime - ((HalfSync * 2) + BackPorch + FrontPorch);
|
||
WRITE_REGISTER_ULONG(&VideoControl->ShortDisplay.Long, ShortDisplay);
|
||
|
||
WRITE_REGISTER_ULONG(&VideoControl->BroadPulse.Long, HalfLineTime - FrontPorch);
|
||
|
||
WRITE_REGISTER_ULONG(&VideoControl->VerticalSync.Long, CurrentMonitor->VerticalSync * 2);
|
||
|
||
WRITE_REGISTER_ULONG(&VideoControl->VerticalBlank.Long,
|
||
(CurrentMonitor->VerticalFrontPorch + CurrentMonitor->VerticalBackPorch -
|
||
(CurrentMonitor->VerticalSync * 2)) * 2);
|
||
|
||
WRITE_REGISTER_ULONG(&VideoControl->VerticalDisplay.Long, CurrentMonitor->VerticalResolution * 2);
|
||
|
||
WRITE_REGISTER_ULONG(&VideoControl->LineStart.Long, LINE_START_VALUE);
|
||
|
||
//
|
||
// TransferDelay must be less than BackPorch and ShortDisplay. Note: When
|
||
// 50 MHz chips are everywhere, TransferDelay should have a maximum value
|
||
// to minimize the graphics overhead.
|
||
//
|
||
|
||
if (BackPorch < ShortDisplay) {
|
||
TransferDelay = BackPorch - 1;
|
||
} else {
|
||
TransferDelay = ShortDisplay - 1;
|
||
}
|
||
|
||
WRITE_REGISTER_ULONG(&VideoControl->TransferDelay.Long, TransferDelay);
|
||
|
||
//
|
||
// DMA display (also known as MemInit) is 1024 (the length of the VRAM
|
||
// shift register) minus TransferDelay.
|
||
//
|
||
|
||
DmaDisplay = 1024 - TransferDelay;
|
||
WRITE_REGISTER_ULONG(&VideoControl->DmaDisplay.Long, DmaDisplay);
|
||
|
||
WRITE_REGISTER_ULONG(&VideoControl->PixelMask.Long, G300_PIXEL_MASK_VALUE);
|
||
|
||
//
|
||
// Set up the color map.
|
||
//
|
||
|
||
WRITE_REGISTER_ULONG(&VideoControl->ColorMapData[FW_COLOR_BLACK],
|
||
G300_PALETTE_BLACK);
|
||
WRITE_REGISTER_ULONG(&VideoControl->ColorMapData[FW_COLOR_RED],
|
||
G300_PALETTE_RED);
|
||
WRITE_REGISTER_ULONG(&VideoControl->ColorMapData[FW_COLOR_GREEN],
|
||
G300_PALETTE_GREEN);
|
||
WRITE_REGISTER_ULONG(&VideoControl->ColorMapData[FW_COLOR_YELLOW],
|
||
G300_PALETTE_YELLOW);
|
||
WRITE_REGISTER_ULONG(&VideoControl->ColorMapData[FW_COLOR_BLUE],
|
||
G300_PALETTE_BLUE);
|
||
WRITE_REGISTER_ULONG(&VideoControl->ColorMapData[FW_COLOR_MAGENTA],
|
||
G300_PALETTE_MAGENTA);
|
||
WRITE_REGISTER_ULONG(&VideoControl->ColorMapData[FW_COLOR_CYAN],
|
||
G300_PALETTE_CYAN);
|
||
WRITE_REGISTER_ULONG(&VideoControl->ColorMapData[FW_COLOR_WHITE],
|
||
G300_PALETTE_WHITE);
|
||
WRITE_REGISTER_ULONG(&VideoControl->ColorMapData[FW_COLOR_HI_BLACK],
|
||
G300_PALETTE_HI_BLACK);
|
||
WRITE_REGISTER_ULONG(&VideoControl->ColorMapData[FW_COLOR_HI_RED],
|
||
G300_PALETTE_HI_RED);
|
||
WRITE_REGISTER_ULONG(&VideoControl->ColorMapData[FW_COLOR_HI_GREEN],
|
||
G300_PALETTE_HI_GREEN);
|
||
WRITE_REGISTER_ULONG(&VideoControl->ColorMapData[FW_COLOR_HI_YELLOW],
|
||
G300_PALETTE_HI_YELLOW);
|
||
WRITE_REGISTER_ULONG(&VideoControl->ColorMapData[FW_COLOR_HI_BLUE],
|
||
G300_PALETTE_HI_BLUE);
|
||
WRITE_REGISTER_ULONG(&VideoControl->ColorMapData[FW_COLOR_HI_MAGENTA],
|
||
G300_PALETTE_HI_MAGENTA);
|
||
WRITE_REGISTER_ULONG(&VideoControl->ColorMapData[FW_COLOR_HI_CYAN],
|
||
G300_PALETTE_HI_CYAN);
|
||
WRITE_REGISTER_ULONG(&VideoControl->ColorMapData[FW_COLOR_HI_WHITE],
|
||
G300_PALETTE_HI_WHITE);
|
||
|
||
//
|
||
// Initialize the G300B control parameters.
|
||
//
|
||
|
||
DataLong = 0;
|
||
((PG300_VIDEO_PARAMETERS)(&DataLong))->EnableVideo = 1;
|
||
((PG300_VIDEO_PARAMETERS)(&DataLong))->PlainWave = 1;
|
||
((PG300_VIDEO_PARAMETERS)(&DataLong))->SeparateSync = 1;
|
||
((PG300_VIDEO_PARAMETERS)(&DataLong))->DelaySync = G300_DELAY_SYNC_CYCLES;
|
||
((PG300_VIDEO_PARAMETERS)(&DataLong))->BlankOutput = 1;
|
||
((PG300_VIDEO_PARAMETERS)(&DataLong))->BitsPerPixel = EIGHT_BITS_PER_PIXEL;
|
||
((PG300_VIDEO_PARAMETERS)(&DataLong))->AddressStep = 2;
|
||
WRITE_REGISTER_ULONG(&VideoControl->Parameters.Long, DataLong);
|
||
|
||
//
|
||
// Disable the cursor parts.
|
||
//
|
||
|
||
WRITE_REGISTER_USHORT(&CursorControl->AddressPointer0.Short,0);
|
||
WRITE_REGISTER_USHORT(&CursorControl->AddressPointer1.Short,0);
|
||
|
||
//
|
||
// Clear cursor control.
|
||
//
|
||
|
||
for (i=0;i<13;i++) {
|
||
WRITE_REGISTER_USHORT(&CursorControl->CursorControl.Short,0);
|
||
}
|
||
|
||
//
|
||
// Clear Cursor Memory
|
||
//
|
||
|
||
for (i=0;i<512;i++) {
|
||
WRITE_REGISTER_USHORT(&CursorControl->CursorMemory.Short,0);
|
||
}
|
||
|
||
return ESUCCESS;
|
||
}
|
||
|
||
ARC_STATUS
|
||
InitializeG364 (
|
||
IN OUT PMONITOR_CONFIGURATION_DATA GlobalMonitor
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine initializes the G364 video control registers, and clears the
|
||
video screen.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
If the video was initialized, ESUCCESS is returned, otherwise an error
|
||
code is returned.
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONG ScreenUnitRate;
|
||
ULONG MultiplierValue;
|
||
ULONG HalfLineTime;
|
||
ULONG FrontPorch;
|
||
ULONG BackPorch;
|
||
ULONG HalfSync;
|
||
ULONG TransferDelay;
|
||
ULONG DmaDisplay;
|
||
ULONG DataLong;
|
||
PG364_VIDEO_REGISTERS VideoControl = (PG364_VIDEO_REGISTERS) (VIDEO_CONTROL_VIRTUAL_BASE + 0x80000);
|
||
PMONITOR_CONFIGURATION_DATA CurrentMonitor;
|
||
BOOLEAN UpdateMonitor;
|
||
JAZZ_VIDEO_TYPE FwVideoType;
|
||
|
||
//
|
||
// Determine if this is actually the G364 board.
|
||
//
|
||
|
||
if (READ_REGISTER_UCHAR((PUCHAR)(VIDEO_CONTROL_VIRTUAL_BASE)) == JazzVideoG364) {
|
||
FwVideoType = JazzVideoG364;
|
||
} else {
|
||
FwVideoType = MipsVideoG364;
|
||
}
|
||
|
||
//
|
||
// Reset the whole video board.
|
||
//
|
||
|
||
WRITE_REGISTER_UCHAR((PUCHAR)(VIDEO_CONTROL_VIRTUAL_BASE+0x180000),0);
|
||
|
||
CurrentMonitor = GlobalMonitor;
|
||
UpdateMonitor = FALSE;
|
||
|
||
//
|
||
// Check to see if the Monitor parameters are valid.
|
||
//
|
||
|
||
do {
|
||
|
||
//
|
||
// Determine the desired screen unit rate, in picoseconds (a screen unit is
|
||
// four pixels).
|
||
//
|
||
|
||
if ((CurrentMonitor->HorizontalDisplayTime != 0) && (CurrentMonitor->HorizontalResolution != 0)) {
|
||
ScreenUnitRate = (CurrentMonitor->HorizontalDisplayTime * 1000) * 4 / CurrentMonitor->HorizontalResolution;
|
||
} else {
|
||
continue;
|
||
}
|
||
|
||
if (ScreenUnitRate == 0) {
|
||
continue;
|
||
}
|
||
|
||
//
|
||
// Multiplier value is the oscillator period (in picoseconds) divided by
|
||
// the pixel rate.
|
||
//
|
||
|
||
if (FwVideoType == JazzVideoG364) {
|
||
MultiplierValue = 123077 / (ScreenUnitRate / 4);
|
||
if (MultiplierValue < 5 || MultiplierValue > 18) {
|
||
continue;
|
||
}
|
||
} else {
|
||
MultiplierValue = 200000 / (ScreenUnitRate / 4);
|
||
if (MultiplierValue < 5 || MultiplierValue > 29) {
|
||
continue;
|
||
}
|
||
}
|
||
|
||
|
||
break;
|
||
|
||
//
|
||
// If the while is executed, the parameters are not valid. Set UpdateMonitor
|
||
// and point to the default parameters, which are valid. Note that the
|
||
// "while" will evaluate TRUE because the value of (a,b) is the value of b.
|
||
//
|
||
|
||
} while (CurrentMonitor = &DefaultMonitor, UpdateMonitor = TRUE);
|
||
|
||
//
|
||
// Update the monitor parameters if necessary.
|
||
//
|
||
|
||
if (UpdateMonitor) {
|
||
GlobalMonitor->HorizontalResolution = DefaultMonitor.HorizontalResolution;
|
||
GlobalMonitor->HorizontalDisplayTime = DefaultMonitor.HorizontalDisplayTime;
|
||
GlobalMonitor->HorizontalBackPorch = DefaultMonitor.HorizontalBackPorch;
|
||
GlobalMonitor->HorizontalFrontPorch = DefaultMonitor.HorizontalFrontPorch;
|
||
GlobalMonitor->HorizontalSync = DefaultMonitor.HorizontalSync;
|
||
GlobalMonitor->VerticalResolution = DefaultMonitor.VerticalResolution;
|
||
GlobalMonitor->VerticalBackPorch = DefaultMonitor.VerticalBackPorch;
|
||
GlobalMonitor->VerticalFrontPorch = DefaultMonitor.VerticalFrontPorch;
|
||
GlobalMonitor->VerticalSync = DefaultMonitor.VerticalSync;
|
||
}
|
||
|
||
//
|
||
// write multiplier value
|
||
//
|
||
|
||
DataLong = 0;
|
||
((PG364_VIDEO_BOOT)(&DataLong))->ClockSelect = 1;
|
||
((PG364_VIDEO_BOOT)(&DataLong))->MicroPort64Bits = 1;
|
||
((PG364_VIDEO_BOOT)(&DataLong))->Multiplier = MultiplierValue;
|
||
WRITE_REGISTER_ULONG(&VideoControl->Boot.Long, DataLong);
|
||
|
||
//
|
||
// Initialize the G364 control parameters.
|
||
//
|
||
|
||
DataLong = 0;
|
||
|
||
//
|
||
// If vertical front porch is 1, use tesselated sync, otherwise use normal sync.
|
||
//
|
||
|
||
if (CurrentMonitor->VerticalFrontPorch > 1) {
|
||
((PG364_VIDEO_PARAMETERS)(&DataLong))->PlainSync = 1;
|
||
}
|
||
((PG364_VIDEO_PARAMETERS)(&DataLong))->DelaySync = G364_DELAY_SYNC_CYCLES;
|
||
((PG364_VIDEO_PARAMETERS)(&DataLong))->BitsPerPixel = EIGHT_BITS_PER_PIXEL;
|
||
((PG364_VIDEO_PARAMETERS)(&DataLong))->AddressStep = G364_ADDRESS_STEP_INCREMENT;
|
||
((PG364_VIDEO_PARAMETERS)(&DataLong))->DisableCursor = 1;
|
||
WRITE_REGISTER_ULONG(&VideoControl->Parameters.Long, DataLong);
|
||
|
||
//
|
||
// Initialize the G364 operational values.
|
||
//
|
||
|
||
HalfSync = (CurrentMonitor->HorizontalSync * 1000) / ScreenUnitRate / 2;
|
||
WRITE_REGISTER_ULONG(&VideoControl->HorizontalSync.Long, HalfSync );
|
||
|
||
BackPorch = (CurrentMonitor->HorizontalBackPorch * 1000) / ScreenUnitRate;
|
||
WRITE_REGISTER_ULONG(&VideoControl->BackPorch.Long, BackPorch );
|
||
|
||
WRITE_REGISTER_ULONG(&VideoControl->Display.Long, CurrentMonitor->HorizontalResolution / 4);
|
||
|
||
//
|
||
// The LineTime needs to be an even number of units, so calculate LineTime / 2
|
||
// and then multiply by two to program. ShortDisplay and BroadPulse also
|
||
// use LineTime / 2.
|
||
//
|
||
|
||
HalfLineTime = (CurrentMonitor->HorizontalSync + CurrentMonitor->HorizontalFrontPorch +
|
||
CurrentMonitor->HorizontalBackPorch + CurrentMonitor->HorizontalDisplayTime) * 1000 /
|
||
ScreenUnitRate / 2;
|
||
|
||
WRITE_REGISTER_ULONG(&VideoControl->LineTime.Long, HalfLineTime * 2);
|
||
|
||
FrontPorch = (CurrentMonitor->HorizontalFrontPorch * 1000) / ScreenUnitRate;
|
||
WRITE_REGISTER_ULONG(&VideoControl->ShortDisplay.Long,
|
||
HalfLineTime - ((HalfSync * 2) + BackPorch + FrontPorch));
|
||
|
||
WRITE_REGISTER_ULONG(&VideoControl->BroadPulse.Long, HalfLineTime - FrontPorch);
|
||
|
||
WRITE_REGISTER_ULONG(&VideoControl->VerticalSync.Long, CurrentMonitor->VerticalSync * 2);
|
||
WRITE_REGISTER_ULONG(&VideoControl->VerticalPreEqualize.Long, CurrentMonitor->VerticalFrontPorch * 2);
|
||
WRITE_REGISTER_ULONG(&VideoControl->VerticalPostEqualize.Long, 1 * 2);
|
||
|
||
WRITE_REGISTER_ULONG(&VideoControl->VerticalBlank.Long,
|
||
(CurrentMonitor->VerticalBackPorch - 1) * 2);
|
||
|
||
WRITE_REGISTER_ULONG(&VideoControl->VerticalDisplay.Long, CurrentMonitor->VerticalResolution * 2);
|
||
|
||
WRITE_REGISTER_ULONG(&VideoControl->LineStart.Long, LINE_START_VALUE);
|
||
|
||
//
|
||
// Transfer delay is 1.65 microseconds expressed in screen units, plus 1.
|
||
//
|
||
|
||
TransferDelay = (1650000 / ScreenUnitRate) + 1;
|
||
|
||
if (BackPorch <= TransferDelay) {
|
||
TransferDelay = BackPorch - 1;
|
||
}
|
||
WRITE_REGISTER_ULONG(&VideoControl->TransferDelay.Long, TransferDelay);
|
||
|
||
//
|
||
// DMA display (also known as MemInit) is 1024 (the length of the VRAM
|
||
// shift register) minus TransferDelay.
|
||
//
|
||
|
||
DmaDisplay = 1024 - TransferDelay;
|
||
WRITE_REGISTER_ULONG(&VideoControl->DmaDisplay.Long, DmaDisplay);
|
||
|
||
WRITE_REGISTER_ULONG(&VideoControl->PixelMask.Long, G364_PIXEL_MASK_VALUE);
|
||
|
||
//
|
||
// Set up the color map.
|
||
//
|
||
|
||
WRITE_REGISTER_ULONG(&VideoControl->ColorMapData[FW_COLOR_BLACK],
|
||
G364_PALETTE_BLACK);
|
||
WRITE_REGISTER_ULONG(&VideoControl->ColorMapData[FW_COLOR_RED],
|
||
G364_PALETTE_RED);
|
||
WRITE_REGISTER_ULONG(&VideoControl->ColorMapData[FW_COLOR_GREEN],
|
||
G364_PALETTE_GREEN);
|
||
WRITE_REGISTER_ULONG(&VideoControl->ColorMapData[FW_COLOR_YELLOW],
|
||
G364_PALETTE_YELLOW);
|
||
WRITE_REGISTER_ULONG(&VideoControl->ColorMapData[FW_COLOR_BLUE],
|
||
G364_PALETTE_BLUE);
|
||
WRITE_REGISTER_ULONG(&VideoControl->ColorMapData[FW_COLOR_MAGENTA],
|
||
G364_PALETTE_MAGENTA);
|
||
WRITE_REGISTER_ULONG(&VideoControl->ColorMapData[FW_COLOR_CYAN],
|
||
G364_PALETTE_CYAN);
|
||
WRITE_REGISTER_ULONG(&VideoControl->ColorMapData[FW_COLOR_WHITE],
|
||
G364_PALETTE_WHITE);
|
||
WRITE_REGISTER_ULONG(&VideoControl->ColorMapData[FW_COLOR_HI_BLACK],
|
||
G364_PALETTE_HI_BLACK);
|
||
WRITE_REGISTER_ULONG(&VideoControl->ColorMapData[FW_COLOR_HI_RED],
|
||
G364_PALETTE_HI_RED);
|
||
WRITE_REGISTER_ULONG(&VideoControl->ColorMapData[FW_COLOR_HI_GREEN],
|
||
G364_PALETTE_HI_GREEN);
|
||
WRITE_REGISTER_ULONG(&VideoControl->ColorMapData[FW_COLOR_HI_YELLOW],
|
||
G364_PALETTE_HI_YELLOW);
|
||
WRITE_REGISTER_ULONG(&VideoControl->ColorMapData[FW_COLOR_HI_BLUE],
|
||
G364_PALETTE_HI_BLUE);
|
||
WRITE_REGISTER_ULONG(&VideoControl->ColorMapData[FW_COLOR_HI_MAGENTA],
|
||
G364_PALETTE_HI_MAGENTA);
|
||
WRITE_REGISTER_ULONG(&VideoControl->ColorMapData[FW_COLOR_HI_CYAN],
|
||
G364_PALETTE_HI_CYAN);
|
||
WRITE_REGISTER_ULONG(&VideoControl->ColorMapData[FW_COLOR_HI_WHITE],
|
||
G364_PALETTE_HI_WHITE);
|
||
|
||
//
|
||
// Enable the G364
|
||
//
|
||
|
||
((PG364_VIDEO_PARAMETERS)(&DataLong))->EnableVideo = 1;
|
||
WRITE_REGISTER_ULONG(&VideoControl->Parameters.Long, DataLong);
|
||
|
||
//
|
||
// G364 C04 bug # 6:
|
||
// "The action of starting the VTG may cause the TopOfScreen register to become corrupted"
|
||
//
|
||
|
||
WRITE_REGISTER_ULONG(&VideoControl->TopOfScreen, 0);
|
||
|
||
return ESUCCESS;
|
||
}
|
||
|
||
|
||
|
||
|
||
VOID
|
||
DisplayInitialize (
|
||
IN OUT PDRIVER_LOOKUP_ENTRY LookupTableEntry,
|
||
IN ULONG Entries
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine initializes the video entry in the driver lookup table.
|
||
|
||
Arguments:
|
||
|
||
LookupTableEntry - Supplies a pointer to the first free location in the
|
||
driver lookup table.
|
||
|
||
Entries - Supplies the number of free entries in the driver lookup table.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
//
|
||
// Initialize the driver lookup table, and increment the pointer.
|
||
//
|
||
|
||
LookupTableEntry->DevicePath = DisplayDevicePath;
|
||
LookupTableEntry->DispatchTable = &DisplayEntryTable;
|
||
|
||
return;
|
||
}
|
||
|
||
VOID
|
||
FwDisplayCharacter (
|
||
IN UCHAR Character
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine displays a single character on the video screen at the current
|
||
cursor location with the current color and video attributes. It finds the
|
||
font bitmap and calls VenOutputCharacter to actually do the display.
|
||
|
||
Arguments:
|
||
|
||
Character - Supplies the character to be displayed.
|
||
|
||
LineDrawCharacter - If true the current character is a line drawing character.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
VenOutputCharacter((PVOID)&FwFont[(Character - 1) * CharacterSize],
|
||
FwRow,
|
||
FwColumn);
|
||
return;
|
||
}
|
||
|
||
VOID
|
||
FwOutputCharacter (
|
||
IN PVOID Character,
|
||
IN ULONG Row,
|
||
IN ULONG Column
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine displays a single character on the video screen at the current
|
||
cursor location with the current color and video attributes. It assumes
|
||
the character locations are word aligned.
|
||
|
||
Arguments:
|
||
|
||
Character - Supplies the character to be displayed.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
UCHAR DataByte;
|
||
PULONG Destination;
|
||
PUSHORT ShortDestination;
|
||
ULONG I;
|
||
|
||
Destination = (PULONG)(VIDEO_MEMORY +
|
||
(Row * ScrollLine) + (Column * CharacterWidth));
|
||
|
||
if (CharacterWidth == 10) {
|
||
ShortDestination = (PUSHORT)Destination;
|
||
|
||
for (I = 0; I < CharacterHeight; I += 1) {
|
||
DataByte = *((PUCHAR)Character)++;
|
||
*ShortDestination++ = (USHORT)ColorTable[DataByte & 0x03];
|
||
*ShortDestination++ = (USHORT)ColorTable[(DataByte >> 2) & 0x03];
|
||
*ShortDestination++ = (USHORT)ColorTable[(DataByte >> 4) & 0x03];
|
||
*ShortDestination++ = (USHORT)ColorTable[(DataByte >> 6) & 0x03];
|
||
DataByte = *((PUCHAR)Character)++;
|
||
*ShortDestination++ = (USHORT)ColorTable[DataByte & 0x03];
|
||
ShortDestination += FontIncrement;
|
||
|
||
}
|
||
} else {
|
||
for (I = 0; I < CharacterHeight; I += 1) {
|
||
DataByte = *((PUCHAR)Character)++;
|
||
*Destination++ = ColorTable[DataByte & 0x0f];
|
||
*Destination++ = ColorTable[DataByte >> 4];
|
||
Destination += FontIncrement;
|
||
}
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
VOID
|
||
FwScrollVideo (
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine scrolls the display up one line.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONG SaveColumn;
|
||
|
||
//
|
||
// Call the assembly language routine to do the actual scroll.
|
||
//
|
||
|
||
FwVideoScroll((PVOID)(VIDEO_MEMORY + ScrollLine),
|
||
(PVOID)(VIDEO_MEMORY + ScrollLine + ScrollLength),
|
||
(PVOID)VIDEO_MEMORY);
|
||
|
||
SaveColumn = FwColumn;
|
||
|
||
//
|
||
// Set the bottom line to be the background color.
|
||
//
|
||
|
||
for (FwColumn = MaxColumn ;
|
||
FwColumn >= 0 ;
|
||
FwColumn-- ) {
|
||
FwDisplayCharacter(' ');
|
||
}
|
||
|
||
FwColumn = SaveColumn;
|
||
return;
|
||
}
|
||
|
||
VOID
|
||
FwSetDisplayAttributes (
|
||
IN ULONG ForegroundColor,
|
||
IN ULONG BackgroundColor,
|
||
IN BOOLEAN HighIntensity,
|
||
IN BOOLEAN Underscored,
|
||
IN BOOLEAN ReverseVideo,
|
||
IN ULONG CharacterWidth,
|
||
IN ULONG CharacterHeight
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This is a dummy routine that can be replaced by the video prom.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
return;
|
||
}
|
||
|
||
VOID
|
||
FwSetAllAttributes (
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine calls the vendor routine to set all of the screen attributes.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
VenSetDisplayAttributes(FwForegroundColor,
|
||
FwBackgroundColor,
|
||
FwHighIntensity,
|
||
FwUnderscored,
|
||
FwReverseVideo,
|
||
CharacterWidth,
|
||
CharacterHeight
|
||
);
|
||
|
||
return;
|
||
}
|
||
|
||
ARC_STATUS
|
||
FwTestUnicodeCharacter (
|
||
IN ULONG FileId,
|
||
IN WCHAR UnicodeCharacter
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine checks for the existence of a valid glyph corresponding to
|
||
UnicodeCharacter.
|
||
|
||
Arguments:
|
||
|
||
FileId - Supplies the FileId of the output device.
|
||
|
||
UnicodeCharacter - Supplies the UNICODE character to be tested.
|
||
|
||
Return Value:
|
||
|
||
If writing UnicodeCharacter to the device specified by FileId would
|
||
result in the display of a valid glyph on the output device, then
|
||
ESUCCESS is returned. If the device does not support the character,
|
||
the EINVAL is returned.
|
||
|
||
--*/
|
||
{
|
||
if (((UnicodeCharacter >= ' ') && (UnicodeCharacter <= '~')) ||
|
||
((UnicodeCharacter >= 0x2500) && (UnicodeCharacter <= 0x257f))) {
|
||
return(ESUCCESS);
|
||
} else {
|
||
return(EINVAL);
|
||
}
|
||
}
|
||
|
||
|
||
PARC_DISPLAY_STATUS
|
||
FwGetDisplayStatus (
|
||
IN ULONG FileId
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
|
||
--*/
|
||
{
|
||
DisplayStatus.CursorXPosition = FwColumn + 1;
|
||
DisplayStatus.CursorYPosition = FwRow + 1;
|
||
DisplayStatus.CursorMaxXPosition = MaxColumn + 1;
|
||
DisplayStatus.CursorMaxYPosition = MaxRow + 1;
|
||
DisplayStatus.ForegroundColor = FwForegroundColor;
|
||
DisplayStatus.BackgroundColor = FwBackgroundColor;
|
||
DisplayStatus.HighIntensity = FwHighIntensity;
|
||
DisplayStatus.Underscored = FwUnderscored;
|
||
DisplayStatus.ReverseVideo = FwReverseVideo;
|
||
|
||
return(&DisplayStatus);
|
||
}
|