mirror of https://github.com/lianthony/NT4.0
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.
2086 lines
55 KiB
2086 lines
55 KiB
#if defined(JAZZ)
|
|
|
|
/*++
|
|
|
|
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 "selftest.h"
|
|
#include "string.h"
|
|
#include "duobase.h"
|
|
#include "duoreset.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
|
|
DisplayWrite (
|
|
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)
|
|
|
|
|
|
//
|
|
// Static data.
|
|
//
|
|
|
|
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;
|
|
ULONG MaxRow;
|
|
ULONG MaxColumn;
|
|
ULONG CharacterHeight;
|
|
ULONG CharacterWidth;
|
|
ULONG CharacterSize;
|
|
PCHAR FwFont;
|
|
PCHAR FwLineDrawFont;
|
|
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
|
|
|
|
ULONG Parameter[CONTROL_SEQUENCE_MAX_PARAMETER];
|
|
|
|
//
|
|
// Declare and initialize the default DefaultMonitor.
|
|
//
|
|
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
|
|
};
|
|
|
|
UCHAR LdHorizontalMask[12][4] = { 0xf8, 0x0f, 0x08, 0x08,
|
|
0xcc, 0xcc, 0x08, 0x1c,
|
|
0x5b, 0x5b, 0x08, 0x1c,
|
|
0xaa, 0xaa, 0x08, 0x1c,
|
|
0xf8, 0x0f, 0x1c, 0x1c,
|
|
0x10, 0x04, 0x1c, 0x1c,
|
|
0x10, 0x04, 0x08, 0x08,
|
|
0xf0, 0x07, 0x08, 0x08,
|
|
0xf0, 0x07, 0x14, 0x14,
|
|
0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0xaa, 0x55 };
|
|
|
|
USHORT LdVerticalMask[12][4] = { 0x0080, 0x0080, 0x00ff, 0xff80,
|
|
0x0080, 0x01c0, 0x0f0f, 0x0f0f,
|
|
0x0080, 0x01c0, 0xe31c, 0xe31c,
|
|
0x0080, 0x01c0, 0x3333, 0x3333,
|
|
0x01c0, 0x01c0, 0x00ff, 0xff80,
|
|
0x01c0, 0x01c0, 0x0040, 0x0100,
|
|
0x0080, 0x0080, 0x0040, 0x0100,
|
|
0x0080, 0x0080, 0x007f, 0xff00,
|
|
0x0140, 0x0140, 0x007f, 0xff00,
|
|
0x0000, 0x0000, 0x0000, 0x0000,
|
|
0x0000, 0x0000, 0x0000, 0x0000,
|
|
0x0000, 0x0000, 0xaaaa, 0x5555 };
|
|
|
|
|
|
UCHAR LdAsciiToUnicode[40] = {0x02, 0x24, 0x61, 0x62, 0x56, 0x55, 0x63, 0x51,
|
|
0x57, 0x5d, 0x5c, 0x5b, 0x10, 0x14, 0x34, 0x2c,
|
|
0x1c, 0x00, 0x3c, 0x5e, 0x5f, 0x5a, 0x54, 0x69,
|
|
0x66, 0x60, 0x50, 0x6c, 0x67, 0x68, 0x64, 0x65,
|
|
0x59, 0x58, 0x52, 0x53, 0x6b, 0x6a, 0x18, 0x0c };
|
|
|
|
//
|
|
// Declare externally defined data.
|
|
//
|
|
|
|
extern UCHAR FwUsFont2[1];
|
|
extern UCHAR FwRleFont[1];
|
|
extern UCHAR FwLdFont[1];
|
|
|
|
|
|
//
|
|
// Define routine prototypes.
|
|
//
|
|
|
|
VOID
|
|
FwDisplayCharacter(
|
|
IN UCHAR Character,
|
|
IN BOOLEAN LineDrawCharacter
|
|
);
|
|
|
|
|
|
|
|
ULONG
|
|
FwPrint (
|
|
PCHAR Format,
|
|
...
|
|
)
|
|
|
|
{
|
|
|
|
va_list arglist;
|
|
UCHAR Buffer[256];
|
|
ULONG Count;
|
|
ULONG Length;
|
|
|
|
//
|
|
// Format the output into a buffer and then print it.
|
|
//
|
|
|
|
va_start(arglist, Format);
|
|
Length = vsprintf(Buffer, Format, arglist);
|
|
DisplayWrite(Buffer, Length, &Count);
|
|
va_end(arglist);
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
FwUnpackBitmap(
|
|
IN UCHAR HorizontalMask,
|
|
IN USHORT VerticalMask,
|
|
OUT PUCHAR Bitmap
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine unpacks a bitmap that has been stored using the two-byte
|
|
per glyph encoding scheme. It is typically called four times per
|
|
glyph, for top, bottom, left, and right.
|
|
|
|
Arguments:
|
|
|
|
HorizontalMask - Supplies a horizontal mask value.
|
|
|
|
Vertical Mask - Supplies a vertical mask value.
|
|
|
|
Bitmap - Supplies a pointer to the output bitmap.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
PUCHAR TempChar;
|
|
PUSHORT TempShort;
|
|
ULONG I, J;
|
|
|
|
//
|
|
// Check for 16x32 font.
|
|
//
|
|
|
|
if (CharacterWidth == 16) {
|
|
|
|
TempShort = (PUSHORT)Bitmap;
|
|
|
|
//
|
|
// Loop 16 times, drawing two lines per loop.
|
|
//
|
|
|
|
for ( I = 1 ; I <= 0x8000; I <<= 1 ) {
|
|
|
|
//
|
|
// If the vertical mask is set, draw the horizontal mask.
|
|
//
|
|
|
|
if (I & VerticalMask) {
|
|
|
|
//
|
|
// Stretch the horizontal mask out by a factor of two.
|
|
//
|
|
|
|
for (J = 0 ; J < 8 ; J++ ) {
|
|
if ((1 << J) & HorizontalMask) {
|
|
*TempShort |= 3 << (J * 2);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Duplicate the line and increment the pointer.
|
|
//
|
|
|
|
*(TempShort + 1) = *TempShort;
|
|
TempShort += 2;
|
|
}
|
|
|
|
//
|
|
// Assume 16x8 font.
|
|
//
|
|
|
|
} else {
|
|
|
|
TempChar = Bitmap;
|
|
|
|
//
|
|
// Loop 16 times.
|
|
//
|
|
|
|
for ( I = 1 ; I <= 0x8000; I <<= 1 ) {
|
|
|
|
//
|
|
// If the vertical mask is set, draw the horizontal mask.
|
|
//
|
|
|
|
if (I & VerticalMask) {
|
|
*TempChar |= HorizontalMask;
|
|
}
|
|
TempChar++;
|
|
}
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
ARC_STATUS
|
|
DisplayWrite (
|
|
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:
|
|
|
|
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;
|
|
ULONG ColumnEndPoint;
|
|
ULONG RowEndPoint;
|
|
ULONG Index, Index2;
|
|
ULONG FGColor;
|
|
ULONG BGColor;
|
|
BOOLEAN Unicode;
|
|
|
|
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(*String, TRUE);
|
|
} else {
|
|
FwDisplayCharacter(128, TRUE);
|
|
}
|
|
|
|
if (FwColumn < MaxColumn) {
|
|
FwColumn++;
|
|
}
|
|
continue;
|
|
} else {
|
|
if (*(String + 1) != 0) {
|
|
|
|
//
|
|
// Display an invalid character.
|
|
//
|
|
|
|
FwDisplayCharacter(128, TRUE);
|
|
|
|
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(' ', FALSE);
|
|
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(' ', FALSE);
|
|
}
|
|
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(' ', FALSE);
|
|
} while (FwColumn != ColumnEndPoint);
|
|
break;
|
|
|
|
//
|
|
// Erase from the beginning of the line.
|
|
//
|
|
|
|
case 1:
|
|
ColumnEndPoint = FwColumn;
|
|
FwColumn = -1;
|
|
do {
|
|
FwColumn++;
|
|
FwDisplayCharacter(' ', FALSE);
|
|
} while (FwColumn != ColumnEndPoint);
|
|
break;
|
|
|
|
//
|
|
// Erase entire line.
|
|
//
|
|
|
|
default :
|
|
FwColumn = MaxColumn + 1;
|
|
do {
|
|
FwColumn--;
|
|
FwDisplayCharacter(' ', FALSE);
|
|
} 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;
|
|
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 line drawing character
|
|
//
|
|
|
|
if ((*String >= '³') && (*String <= 'Ú')) {
|
|
FwDisplayCharacter(LdAsciiToUnicode[*String - '³'], TRUE);
|
|
|
|
if (FwColumn < MaxColumn) {
|
|
FwColumn++;
|
|
}
|
|
|
|
//
|
|
// Check for printing character.
|
|
//
|
|
|
|
} else if (((*String >= ' ') && (*String <= '~'))) {
|
|
|
|
FwDisplayCharacter(*String, FALSE);
|
|
|
|
if (FwColumn < MaxColumn) {
|
|
FwColumn++;
|
|
}
|
|
|
|
} 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) {
|
|
FwScrollVideo();
|
|
} 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:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
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;
|
|
ULONG Character;
|
|
ULONG I,J,K;
|
|
ULONG Side;
|
|
PUCHAR LdFont;
|
|
PUSHORT FontWord;
|
|
ULONG LdFontSize;
|
|
ULONG FontIndex;
|
|
BOOLEAN Bitmap[32*16];
|
|
ULONG BitmapIndex;
|
|
ULONG Short, Byte, Bit;
|
|
JAZZ_VIDEO_TYPE VideoType;
|
|
|
|
//
|
|
// Try to initialize G300.
|
|
//
|
|
|
|
Status = ESUCCESS;
|
|
if (InitializeG300(&DefaultMonitor) != ESUCCESS) {
|
|
|
|
//
|
|
// G300 did not initialize properly, try a video PROM.
|
|
//
|
|
|
|
if (InitializeVideoFromProm(&DefaultMonitor) != ESUCCESS) {
|
|
|
|
//
|
|
// There is no valid video PROM, try for a G364 without a video
|
|
// PROM.
|
|
//
|
|
|
|
if (InitializeG364(&DefaultMonitor) != ESUCCESS) {
|
|
//
|
|
// No valid video initialization was found.
|
|
//
|
|
|
|
Status = EINVAL;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// 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_BLUE;
|
|
DisplayWidth = DefaultMonitor.HorizontalResolution;
|
|
FrameSize = (DisplayWidth * DefaultMonitor.VerticalResolution);
|
|
|
|
if (DisplayWidth >= 1280) {
|
|
CharacterHeight = 32;
|
|
CharacterWidth = 16;
|
|
CharacterSize = (CharacterHeight * (CharacterWidth / 8));
|
|
} else {
|
|
CharacterHeight = 16;
|
|
CharacterWidth = 8;
|
|
CharacterSize = (CharacterHeight * (CharacterWidth / 8));
|
|
}
|
|
|
|
ScrollLine = (DisplayWidth * CharacterHeight);
|
|
ScrollLength = (ScrollLine * ((DefaultMonitor.VerticalResolution / CharacterHeight) - 1));
|
|
MaxRow = ((DefaultMonitor.VerticalResolution / CharacterHeight) - 1);
|
|
MaxColumn = ((DisplayWidth / CharacterWidth) - 1);
|
|
FontIncrement = (DisplayWidth - CharacterWidth) / sizeof(ULONG);
|
|
|
|
//
|
|
// Clear the line drawing font area.
|
|
//
|
|
|
|
LdFontSize = (CharacterSize * 130);
|
|
RtlZeroMemory(FW_FONT_ADDRESS, LdFontSize);
|
|
|
|
//
|
|
// Unpack the line drawing font.
|
|
//
|
|
|
|
FwLineDrawFont = (PUCHAR)FW_FONT_ADDRESS;
|
|
LdFont = FwLdFont;
|
|
|
|
for (Character = 0; Character < 129 ; Character++ ) {
|
|
Side = *LdFont >> 4;
|
|
if (Side != 0) {
|
|
Side -= 4;
|
|
FwUnpackBitmap(LdHorizontalMask[Side][0], LdVerticalMask[Side][0],FwLineDrawFont);
|
|
}
|
|
Side = *LdFont++ & 0xf;
|
|
if (Side != 0) {
|
|
Side -= 4;
|
|
FwUnpackBitmap(LdHorizontalMask[Side][1], LdVerticalMask[Side][1],FwLineDrawFont);
|
|
}
|
|
Side = *LdFont >> 4;
|
|
if (Side != 0) {
|
|
Side -= 4;
|
|
FwUnpackBitmap(LdHorizontalMask[Side][2], LdVerticalMask[Side][2],FwLineDrawFont);
|
|
}
|
|
Side = *LdFont++ & 0xf;
|
|
if (Side != 0) {
|
|
Side -= 4;
|
|
FwUnpackBitmap(LdHorizontalMask[Side][3], LdVerticalMask[Side][3],FwLineDrawFont);
|
|
}
|
|
FwLineDrawFont += CharacterHeight * (CharacterWidth / 8);
|
|
}
|
|
|
|
//
|
|
// Reinitialize the pointer.
|
|
//
|
|
|
|
FwLineDrawFont = (PUCHAR)FW_FONT_ADDRESS;
|
|
|
|
//
|
|
// Unpack the ascii font.
|
|
//
|
|
|
|
if (CharacterWidth == 16) {
|
|
|
|
//
|
|
// Clear the first character (the space).
|
|
//
|
|
|
|
FwFont = (PUCHAR)FW_FONT_ADDRESS + LdFontSize;
|
|
for (I = 0; I < CharacterSize ; I++ ) {
|
|
FwFont[I] = 0;
|
|
}
|
|
|
|
//
|
|
// Unpack the RLE font.
|
|
//
|
|
|
|
FontIndex = 0;
|
|
for ( Character = 1; Character < 95 ; Character++ ) {
|
|
|
|
BitmapIndex = 0;
|
|
|
|
//
|
|
// White space at the beginning of the character.
|
|
//
|
|
|
|
for (I = FwRleFont[FontIndex++]; I ; I-- ) {
|
|
Bitmap[BitmapIndex++] = FALSE;
|
|
}
|
|
|
|
//
|
|
// Unpack set/clear pairs until the end.
|
|
//
|
|
|
|
while (Byte = FwRleFont[FontIndex++]) {
|
|
|
|
//
|
|
// Set bits.
|
|
//
|
|
|
|
for (I = Byte >> 4; I ; I-- ) {
|
|
Bitmap[BitmapIndex++] = TRUE;
|
|
}
|
|
|
|
//
|
|
// Clear bits.
|
|
//
|
|
|
|
for (I = Byte & 0xF; I ; I-- ) {
|
|
Bitmap[BitmapIndex++] = FALSE;
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Clear until the end.
|
|
//
|
|
|
|
while (BitmapIndex < CharacterHeight*CharacterWidth) {
|
|
Bitmap[BitmapIndex++] = FALSE;
|
|
}
|
|
|
|
//
|
|
// Pack the font.
|
|
//
|
|
|
|
FontWord = (PUSHORT)(FwFont + (Character * CharacterSize));
|
|
for (Short = 0; Short < CharacterHeight ; Short++ ) {
|
|
FontWord[Short] = 0;
|
|
for (Bit = 0; Bit < CharacterWidth ; Bit++) {
|
|
if (Bitmap[(Short*CharacterWidth) + Bit] ) {
|
|
FontWord[Short] |= 0x8000 >> Bit;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
|
|
//
|
|
// The small font is not packed.
|
|
//
|
|
|
|
FwFont = FwUsFont2;
|
|
}
|
|
|
|
//
|
|
// Set the video memory to the background color.
|
|
//
|
|
|
|
FillVideoMemory(VIDEO_MEMORY,FrameSize,FwBackgroundColor);
|
|
|
|
|
|
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 Index;
|
|
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;
|
|
ULONG Index;
|
|
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
|
|
FwDisplayCharacter (
|
|
IN UCHAR Character,
|
|
IN BOOLEAN LineDrawCharacter
|
|
)
|
|
|
|
/*++
|
|
|
|
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 FwOutputCharacter 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.
|
|
|
|
--*/
|
|
|
|
{
|
|
PULONG Destination;
|
|
|
|
Destination = (PULONG)(VIDEO_MEMORY +
|
|
(FwRow * ScrollLine) + (FwColumn * CharacterWidth));
|
|
|
|
if (!LineDrawCharacter) {
|
|
|
|
FwOutputCharacter((PVOID)&FwFont[(Character - 0x20) * CharacterSize],
|
|
FwRow,
|
|
FwColumn);
|
|
} else {
|
|
|
|
FwOutputCharacter((PVOID)&FwLineDrawFont[Character * 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;
|
|
USHORT DataShort;
|
|
PULONG Destination;
|
|
ULONG I, J;
|
|
|
|
Destination = (PULONG)(VIDEO_MEMORY +
|
|
(Row * ScrollLine) + (Column * CharacterWidth));
|
|
|
|
if (CharacterWidth == 16) {
|
|
for (I = 0; I < CharacterHeight; I += 1) {
|
|
DataShort = *((PUSHORT)Character)++;
|
|
*Destination++ = ColorTable[DataShort & 0x0f];
|
|
*Destination++ = ColorTable[(DataShort >> 4) & 0x0f];
|
|
*Destination++ = ColorTable[(DataShort >> 8) & 0x0f];
|
|
*Destination++ = ColorTable[DataShort >> 12];
|
|
Destination += FontIncrement;
|
|
}
|
|
} else if (CharacterWidth == 12) {
|
|
for (I = 0; I < CharacterHeight; I += 2) {
|
|
|
|
DataByte = *((PUCHAR)Character)++;
|
|
*Destination++ = ColorTable[DataByte & 0x0f];
|
|
*Destination++ = ColorTable[(DataByte >> 4) & 0x0f];
|
|
DataByte = *((PUCHAR)Character)++;
|
|
*Destination++ = ColorTable[DataByte & 0x0f];
|
|
Destination += FontIncrement;
|
|
|
|
*Destination++ = ColorTable[(DataByte >> 4) & 0x0f];
|
|
DataByte = *((PUCHAR)Character)++;
|
|
*Destination++ = ColorTable[DataByte & 0x0f];
|
|
*Destination++ = ColorTable[(DataByte >> 4) & 0x0f];
|
|
Destination += 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(' ', FALSE);
|
|
}
|
|
|
|
FwColumn = SaveColumn;
|
|
return;
|
|
}
|
|
|
|
|
|
VOID
|
|
FwStallExecution (
|
|
IN ULONG MicroSeconds
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function stalls execution for the specified number of microseconds.
|
|
|
|
Arguments:
|
|
|
|
MicroSeconds - Supplies the number of microseconds that execution is to be
|
|
stalled.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
ULONG Index;
|
|
ULONG Limit;
|
|
PULONG Store;
|
|
ULONG Value;
|
|
|
|
//
|
|
// ****** begin temporary code ******
|
|
//
|
|
// This code must be replaced with a smarter version. For now it assumes
|
|
// an execution rate of 50,000,000 instructions per second and 4 instructions
|
|
// per iteration.
|
|
//
|
|
|
|
Store = &Value;
|
|
Limit = (MicroSeconds * 50 / 4);
|
|
for (Index = 0; Index < Limit; Index += 1) {
|
|
*Store = Index;
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
#endif
|