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.
1572 lines
40 KiB
1572 lines
40 KiB
/*++
|
|
|
|
Copyright (c) 1994 NeTpower, Inc.
|
|
|
|
Module Name:
|
|
|
|
jxdisp.c
|
|
|
|
Abstract:
|
|
|
|
This module implements the HAL display initialization and output routines
|
|
for the NeTpower Series 100, 200, 300, Server 1000 with 805 S3 cards,
|
|
928 S3 cards and the NeTpower NeTgraphics 1280 24-bit card. Since the
|
|
NeTpower machines are derived from the ACER PICA machines, this HAL will
|
|
work on those machines as well.
|
|
|
|
Author:
|
|
|
|
Mike Dove (mdove), 28-Mar-94
|
|
|
|
Environment:
|
|
|
|
Kernel mode
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "halp.h"
|
|
#include "vga.h"
|
|
#include "string.h"
|
|
|
|
//
|
|
// Put all code for HAL initialization in the INIT section. It will be
|
|
// deallocated by memory management when phase 1 initialization is
|
|
// completed.
|
|
//
|
|
|
|
#if defined(ALLOC_PRAGMA)
|
|
|
|
#pragma alloc_text(INIT, HalpInitializeDisplay0)
|
|
#pragma alloc_text(INIT, HalpInitializeDisplay1)
|
|
|
|
#endif
|
|
|
|
//
|
|
// Define forward referenced procedure prototypes.
|
|
//
|
|
VOID
|
|
HalpDisplayCharacter (
|
|
IN UCHAR Character
|
|
);
|
|
|
|
VOID
|
|
HalpOutputCharacter (
|
|
IN PUCHAR Glyph
|
|
);
|
|
|
|
VOID
|
|
HalpDisplayVGASetup (
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
HalpDisplayPG1280Setup(
|
|
VOID
|
|
);
|
|
|
|
//
|
|
// The video cards that we support
|
|
//
|
|
|
|
#define PICA_VGA 0
|
|
#define PICA_PG1280 1
|
|
#define ISA_VGA 2
|
|
|
|
#define IS_DISPLAY_VGA ( HalpDisplayType == PICA_VGA || \
|
|
HalpDisplayType == ISA_VGA )
|
|
#define IS_DISPLAY_PG1280 ( HalpDisplayType == PICA_PG1280 )
|
|
|
|
//
|
|
// Define virtual address of the video memory and control registers.
|
|
// Video memory for the PICA S3 card and the PICA PG1280 card are
|
|
// at 40000000. The PICA S3 card has its Control space at 60000000.
|
|
// When an S3 card is on the ISA bus, its Memory is at 91000000 and the
|
|
// Control Space is at 90000000.
|
|
//
|
|
|
|
ULONG VideoMemoryVirtualBase[] = {
|
|
0x40000000, // PICA VGA
|
|
0x40000000, // PICA PG1280 card
|
|
0x40000000 // ISA VGA
|
|
};
|
|
|
|
ULONG VideoMemoryPhysicalBase[] = {
|
|
0x40000000, // PICA VGA
|
|
0x40000000, // PICA PG1280 card
|
|
0x91000000 // ISA VGA
|
|
};
|
|
|
|
ULONG ControlMemoryVirtualBase[] = {
|
|
0x40200000, // PICA VGA
|
|
0x41000000, // PICA PG1280 card
|
|
0x40200000 // ISA VGA
|
|
};
|
|
|
|
ULONG ControlMemoryPhysicalBase[] = {
|
|
0x60000000, // PICA VGA
|
|
0x41000000, // PICA PG1280 card
|
|
0x90000000 // ISA VGA
|
|
};
|
|
|
|
ULONG VideoMemoryBase[] = {
|
|
0x400b8000, // PICA VGA
|
|
0x40000000, // PICA PG1280
|
|
0x400b8000, // ISA VGA
|
|
};
|
|
|
|
//
|
|
// The PICA S3 card simply needs a single PDE page, while the PG1280
|
|
// card needs 5 PDE's...
|
|
//
|
|
|
|
ULONG PDEPages[] = {
|
|
1, // PICA VGA
|
|
5, // PICA PG1280 card
|
|
1, // ISA VGA
|
|
};
|
|
|
|
#define MAX_PDE_PAGES 5
|
|
|
|
#define PG1280_PALETTE_BLUE 0x000000B0
|
|
#define PG1280_PALETTE_HI_WHITE 0xFFFFFFFF
|
|
|
|
//
|
|
//
|
|
//
|
|
typedef
|
|
VOID
|
|
(*PHALP_CONTROLLER_SETUP) (
|
|
VOID
|
|
);
|
|
|
|
|
|
//
|
|
// Define static data.
|
|
//
|
|
|
|
ULONG HalpBytesPerRow;
|
|
ULONG HalpCharacterHeight;
|
|
ULONG HalpCharacterWidth;
|
|
ULONG HalpColumn;
|
|
ULONG HalpDisplayText;
|
|
ULONG HalpDisplayWidth;
|
|
POEM_FONT_FILE_HEADER HalpFontHeader;
|
|
ULONG HalpRow;
|
|
ULONG HalpScrollLength;
|
|
ULONG HalpScrollLine;
|
|
|
|
BOOLEAN HalpDisplayOwnedByHal;
|
|
|
|
ENTRYLO HalpDisplayPte[MAX_PDE_PAGES];
|
|
PHALP_CONTROLLER_SETUP HalpDisplayControllerSetup = NULL;
|
|
MONITOR_CONFIGURATION_DATA HalpMonitorConfigurationData;
|
|
|
|
ULONG HalpColumn;
|
|
ULONG HalpRow;
|
|
ULONG HalpScrollLength;
|
|
ULONG HalpScrollLine;
|
|
ULONG HalpDisplayText;
|
|
ULONG HalpDisplayControlBase = 0;
|
|
|
|
|
|
BOOLEAN HalpDisplayTypeUnknown = FALSE;
|
|
|
|
ULONG HalpDisplayType = 0;
|
|
|
|
//
|
|
// Define macros for reading/writing VGA control and memory space.
|
|
//
|
|
|
|
#define VGA_CREAD ((volatile PVGA_READ_PORT) \
|
|
(ControlMemoryVirtualBase[HalpDisplayType]))
|
|
#define VGA_CWRITE ((volatile PVGA_WRITE_PORT) \
|
|
(ControlMemoryVirtualBase[HalpDisplayType]))
|
|
#define VIDEO_MEMORY ((volatile PUCHAR)(VideoMemoryBase[HalpDisplayType]))
|
|
#define FONT_MEMORY ((volatile PUCHAR)(VideoMemoryVirtualBase[HalpDisplayType]\
|
|
+ 0xA0000))
|
|
|
|
|
|
BOOLEAN
|
|
HalpInitializeDisplay0 (
|
|
IN PLOADER_PARAMETER_BLOCK LoaderBlock
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine maps the video memory and control registers into the user
|
|
part of the idle process address space, initializes the video control
|
|
registers, and clears the video screen.
|
|
|
|
Arguments:
|
|
|
|
LoaderBlock - Supplies a pointer to the loader parameter block.
|
|
|
|
Return Value:
|
|
|
|
If the initialization is successfully completed, than a value of TRUE
|
|
is returned. Otherwise, a value of FALSE is returned.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PCONFIGURATION_COMPONENT_DATA Child;
|
|
PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
|
|
POEM_FONT_FILE_HEADER FontHeader;
|
|
ULONG Index;
|
|
ULONG MatchKey;
|
|
PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor;
|
|
PLIST_ENTRY NextEntry;
|
|
PENTRYLO PageFrame;
|
|
ENTRYLO Pte;
|
|
ULONG StartingPfn;
|
|
ULONG PDECount;
|
|
|
|
//
|
|
// Set the address of the font file header and compute display variables.
|
|
//
|
|
// N.B. The font information suppled by the OS Loader is used during phase
|
|
// 0 initialization. During phase 1 initialization, a pool buffer is
|
|
// allocated and the font information is copied from the OS Loader
|
|
// heap into pool.
|
|
//
|
|
|
|
FontHeader = (POEM_FONT_FILE_HEADER)LoaderBlock->OemFontFile;
|
|
HalpFontHeader = FontHeader;
|
|
HalpBytesPerRow = (FontHeader->PixelWidth + 7) / 8;
|
|
HalpCharacterHeight = FontHeader->PixelHeight;
|
|
HalpCharacterWidth = FontHeader->PixelWidth;
|
|
|
|
//
|
|
// Find the configuration entry for the first display controller.
|
|
//
|
|
|
|
MatchKey = 0;
|
|
ConfigurationEntry=KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
|
|
ControllerClass,
|
|
DisplayController,
|
|
&MatchKey);
|
|
|
|
if (ConfigurationEntry == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Determine which video controller is present in the system.
|
|
// Copy the display controller and monitor parameters in case they are
|
|
// needed later to reinitialize the display to output a message.
|
|
//
|
|
|
|
if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier, "ALI_S3")) {
|
|
|
|
HalpDisplayType = PICA_VGA;
|
|
HalpDisplayControllerSetup = HalpDisplayVGASetup;
|
|
HalpDisplayControlBase = ControlMemoryPhysicalBase[HalpDisplayType];
|
|
|
|
|
|
} else if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier, "S3" )) {
|
|
|
|
HalpDisplayType = ISA_VGA;
|
|
HalpDisplayControllerSetup = HalpDisplayVGASetup;
|
|
HalpDisplayControlBase = ControlMemoryPhysicalBase[HalpDisplayType];
|
|
|
|
} else if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,
|
|
"PG1280P")) {
|
|
|
|
HalpDisplayType = PICA_PG1280;
|
|
HalpDisplayControllerSetup = HalpDisplayPG1280Setup;
|
|
HalpDisplayControlBase = ControlMemoryPhysicalBase[HalpDisplayType];
|
|
} else {
|
|
// Failure condition...
|
|
return FALSE;
|
|
}
|
|
|
|
Child = ConfigurationEntry->Child;
|
|
RtlMoveMemory((PVOID)&HalpMonitorConfigurationData,
|
|
Child->ConfigurationData,
|
|
Child->ComponentEntry.ConfigurationDataLength);
|
|
|
|
//
|
|
// Compute character output display parameters.
|
|
//
|
|
if ( IS_DISPLAY_PG1280 ) {
|
|
HalpDisplayText = 768 / HalpCharacterHeight;
|
|
HalpScrollLine = 8192*HalpCharacterHeight;
|
|
HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
|
|
HalpDisplayWidth = 1024 / HalpCharacterWidth;
|
|
} else {
|
|
// Assume VGA...
|
|
HalpDisplayText = 400 / HalpCharacterHeight;
|
|
HalpScrollLine = 160; // 80 characters + 80
|
|
HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
|
|
HalpDisplayWidth = 80;
|
|
}
|
|
|
|
for ( PDECount = 0; PDECount < PDEPages[HalpDisplayType]; PDECount++ ) {
|
|
|
|
//
|
|
// Scan the memory allocation descriptors and allocate a free page
|
|
// to map the video memory and control registers, and initialize the
|
|
// PDE entry.
|
|
//
|
|
|
|
|
|
NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
|
|
while (NextEntry != &LoaderBlock->MemoryDescriptorListHead) {
|
|
MemoryDescriptor = CONTAINING_RECORD(NextEntry,
|
|
MEMORY_ALLOCATION_DESCRIPTOR,
|
|
ListEntry);
|
|
|
|
if ((MemoryDescriptor->MemoryType == LoaderFree) &&
|
|
(MemoryDescriptor->PageCount > 1)) {
|
|
StartingPfn = MemoryDescriptor->BasePage;
|
|
MemoryDescriptor->BasePage += 1;
|
|
MemoryDescriptor->PageCount -= 1;
|
|
break;
|
|
}
|
|
|
|
NextEntry = NextEntry->Flink;
|
|
}
|
|
|
|
ASSERT(NextEntry != &LoaderBlock->MemoryDescriptorListHead);
|
|
|
|
Pte.X1 = 0;
|
|
Pte.PFN = StartingPfn;
|
|
Pte.G = 0;
|
|
Pte.V = 1;
|
|
Pte.D = 1;
|
|
|
|
#if defined(R3000)
|
|
|
|
Pte.N = 1;
|
|
|
|
#endif
|
|
|
|
#if defined(R4000)
|
|
|
|
Pte.C = UNCACHED_POLICY;
|
|
|
|
#endif
|
|
|
|
//
|
|
// Save the page table page PTE for use in displaying information and
|
|
// map the appropriate PTE in the current page directory page to address
|
|
// the display controller page table page.
|
|
//
|
|
|
|
HalpDisplayPte[PDECount] = Pte;
|
|
*((PENTRYLO)(PDE_BASE |
|
|
(((VideoMemoryVirtualBase[HalpDisplayType] +
|
|
(PDECount*0x400000))
|
|
>> (PDI_SHIFT - 2)) & 0xffc))) = Pte;
|
|
|
|
}
|
|
|
|
//
|
|
// Initialize the page table page.
|
|
//
|
|
|
|
PageFrame = (PENTRYLO)(PTE_BASE |
|
|
(VideoMemoryVirtualBase[HalpDisplayType]
|
|
>> (PDI_SHIFT - PTI_SHIFT)));
|
|
|
|
Pte.PFN = VideoMemoryPhysicalBase[HalpDisplayType] >> PAGE_SHIFT;
|
|
Pte.G = 0;
|
|
Pte.V = 1;
|
|
Pte.D = 1;
|
|
|
|
#if defined(R3000)
|
|
|
|
Pte.N = 1;
|
|
|
|
#endif
|
|
|
|
#if defined(R4000)
|
|
|
|
Pte.C = UNCACHED_POLICY;
|
|
|
|
#endif
|
|
|
|
//
|
|
// page table entries of the video memory
|
|
//
|
|
|
|
for (Index = 0; Index < ( PDEPages[HalpDisplayType] *
|
|
(PAGE_SIZE / sizeof(ENTRYLO)) /
|
|
(HalpDisplayType != PICA_PG1280 ? 2 : 1));
|
|
Index += 1) {
|
|
*PageFrame++ = Pte;
|
|
Pte.PFN += 1;
|
|
}
|
|
|
|
if ( HalpDisplayType != PICA_PG1280 ) {
|
|
Pte.PFN = ControlMemoryPhysicalBase[HalpDisplayType] >> PAGE_SHIFT;
|
|
|
|
for ( Index = 0; Index < 0x10; Index+=1 ) {
|
|
*PageFrame++ = Pte;
|
|
Pte.PFN += 1;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Initialize the display controller.
|
|
//
|
|
HalpDisplayControllerSetup();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOLEAN
|
|
HalpInitializeDisplay1 (
|
|
IN PLOADER_PARAMETER_BLOCK LoaderBlock
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine allocates pool for the OEM font file and copies the font
|
|
information from the OS Loader heap into the allocated pool.
|
|
|
|
Arguments:
|
|
|
|
LoaderBlock - Supplies a pointer to the loader parameter block.
|
|
|
|
Return Value:
|
|
|
|
If the initialization is successfully completed, than a value of TRUE
|
|
is returned. Otherwise, a value of FALSE is returned.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PVOID FontHeader;
|
|
|
|
//
|
|
// Allocate a pool block and copy the OEM font information from the
|
|
// OS Loader heap into the pool block.
|
|
//
|
|
|
|
FontHeader = ExAllocatePool(NonPagedPool, HalpFontHeader->FileSize);
|
|
if (FontHeader == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
RtlMoveMemory(FontHeader, HalpFontHeader, HalpFontHeader->FileSize);
|
|
HalpFontHeader = (POEM_FONT_FILE_HEADER)FontHeader;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
VOID
|
|
HalAcquireDisplayOwnership (
|
|
IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine switches ownership of the display away from the HAL to
|
|
the system display driver. It is called when the system has reached
|
|
a point during bootstrap where it is self supporting and can output
|
|
its own messages. Once ownership has passed to the system display
|
|
driver any attempts to output messages using HalDisplayString must
|
|
result in ownership of the display reverting to the HAL and the
|
|
display hardware reinitialized for use by the HAL.
|
|
|
|
Arguments:
|
|
|
|
ResetDisplayParameters - if non-NULL the address of a function
|
|
the hal can call to reset the video card. The function returns
|
|
TRUE if the display was reset.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
//
|
|
// Set HAL ownership of the display to false.
|
|
//
|
|
|
|
HalpDisplayOwnedByHal = FALSE;
|
|
return;
|
|
}
|
|
|
|
|
|
VOID
|
|
HalpDisplayVGASetup (
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine initializes the VGA display controller chip on the PICA
|
|
or ISA bus.
|
|
|
|
Initialized configuration is to be:
|
|
640 x 480
|
|
80 x 33 characters (with 8x12 font), or 80 x 50 (with 8x8 font)
|
|
16 colors
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
//
|
|
// Initialize the VGA for either PICA or ISA VGA card. This routine is
|
|
// generic VGA, and will attempt NOT to take advantage of any specific VGA
|
|
// implementation. In order to have cleaner code, the eventual goal will be
|
|
// to put the VGA in graphics mode, and address is the same way as a frame
|
|
// buffer. In addition the font is passed to us by the OS loader, thus that
|
|
// is taken care of.
|
|
//
|
|
// Note, that the register sets are loosely configured in order. The values
|
|
// for these registers are taken from page 318 of the Programmers Guide to
|
|
// the EGA and VGA cards, Second Edition by Richard E. Ferraro.
|
|
//
|
|
|
|
ULONG RegisterIndex, RGBIndex, IndexI, IndexJ;
|
|
ULONG DoS3 = 1;
|
|
UCHAR Byte;
|
|
PUCHAR FontData;
|
|
UCHAR Character;
|
|
volatile PUCHAR MemoryByte;
|
|
|
|
// S3 - Put video subsystem into setup mode, and enable it...
|
|
if ( DoS3 ) {
|
|
VGA_CWRITE->VideoSubsystemEnable = ENTER_SETUP_MODE;
|
|
VGA_CWRITE->SetupOptionSelect = VIDEO_SUBSYSTEM_ALIVE;
|
|
VGA_CWRITE->VideoSubsystemEnable = ENABLE_VIDEO_SUBSYSTEM;
|
|
|
|
// The rest of the code in this if statement is to properly
|
|
// re-initalize the S3 chip specifically when coming from
|
|
// graphics mode (bug check for example).
|
|
|
|
// This DISABLES the Enhanced Functions...
|
|
VGA_CWRITE->AdvancedFunctionControl = 0x2;
|
|
|
|
// Unlock the register sets that need modification...
|
|
VGA_CWRITE->CRTCAddress = S3_REGISTER_LOCK_1;
|
|
VGA_CWRITE->CRTCData = 0x48;
|
|
|
|
VGA_CWRITE->CRTCAddress = S3_REGISTER_LOCK_2;
|
|
VGA_CWRITE->CRTCData = 0xa0;
|
|
|
|
// Re-initialize the S3 to a sane mode...
|
|
VGA_CWRITE->CRTCAddress = S3_MEMORY_CONFIGURATION;
|
|
VGA_CWRITE->CRTCData = 0x0;
|
|
|
|
VGA_CWRITE->CRTCAddress = S3_BACKWARD_COMPATIBILITY_3;
|
|
VGA_CWRITE->CRTCData = 0x0;
|
|
|
|
VGA_CWRITE->CRTCAddress = S3_CRT_REGISTER_LOCK;
|
|
VGA_CWRITE->CRTCData = 0x0;
|
|
|
|
VGA_CWRITE->CRTCAddress = S3_MISCELLANEOUS_1;
|
|
VGA_CWRITE->CRTCData = 0x0;
|
|
|
|
VGA_CWRITE->CRTCAddress = S3_MODE_CONTROL;
|
|
VGA_CWRITE->CRTCData = 0x0;
|
|
|
|
VGA_CWRITE->CRTCAddress = S3_HARDWARE_GRAPHICS_CURSOR;
|
|
VGA_CWRITE->CRTCData = 0x0;
|
|
|
|
VGA_CWRITE->CRTCAddress = S3_EXTENDED_MEMORY_CONTROL_1;
|
|
VGA_CWRITE->CRTCData = 0x0;
|
|
|
|
VGA_CWRITE->CRTCAddress = S3_EXTENDED_MEMORY_CONTROL_2;
|
|
VGA_CWRITE->CRTCData = 0x0;
|
|
|
|
VGA_CWRITE->CRTCAddress = S3_LINEAR_ADDRESS_WINDOW_LOW;
|
|
VGA_CWRITE->CRTCData = 0x0;
|
|
|
|
// DISABLES access to Enhanced registers...
|
|
VGA_CWRITE->CRTCAddress = S3_SYSTEM_CONFIGURATION;
|
|
VGA_CWRITE->CRTCData = 0x0;
|
|
|
|
// Lock the register sets that were modified...
|
|
VGA_CWRITE->CRTCAddress = S3_REGISTER_LOCK_2;
|
|
VGA_CWRITE->CRTCData = 0x0;
|
|
|
|
VGA_CWRITE->CRTCAddress = S3_REGISTER_LOCK_1;
|
|
VGA_CWRITE->CRTCData = 0x0;
|
|
}
|
|
|
|
// Do initial synchronus reset...
|
|
VGA_CWRITE->SequencerAddress = SEQ_RESET;
|
|
VGA_CWRITE->SequencerData = SYNCHRONUS_RESET;
|
|
|
|
// Set up initial configuration using the Miscellaneous Output Register
|
|
VGA_CWRITE->MiscOutput = INITIAL_CONFIG;
|
|
|
|
// Do synchronus reset...
|
|
VGA_CWRITE->SequencerAddress = SEQ_RESET;
|
|
VGA_CWRITE->SequencerData = SYNCHRONUS_RESET;
|
|
|
|
// Set up Sequencer registers. Run through the array of data stuffing
|
|
// the values into the VGA. After the Sequencer values have been stuffed,
|
|
// we will return the VGA to normal operation.
|
|
for ( RegisterIndex = SEQ_CLOCKING_MODE; RegisterIndex <= SEQ_MEMORY_MODE;
|
|
RegisterIndex++ ) {
|
|
|
|
VGA_CWRITE->SequencerAddress = (UCHAR)RegisterIndex;
|
|
VGA_CWRITE->SequencerData = SequencerSetup[RegisterIndex];
|
|
|
|
}
|
|
|
|
// Next setup the CRT Controller registers. The registers 0-7 might
|
|
// be write-protected if bit 7 of the Vertical Retrace End register is
|
|
// set. First we will clear that bit, then set all the registers.
|
|
|
|
VGA_CWRITE->CRTCAddress = CRT_VERTICAL_RETRACE_END;
|
|
Byte = VGA_CREAD->CRTCData;
|
|
Byte &= 0x7f;
|
|
VGA_CWRITE->CRTCData = Byte;
|
|
|
|
// Adjust Maximum Scan Lines based on the size of the font passed in
|
|
// by the OSLOADER...
|
|
|
|
CRTCSetup[CRT_MAXIMUM_SCAN_LINE] = (UCHAR)(
|
|
( CRTCSetup[CRT_MAXIMUM_SCAN_LINE] & 0xe0 ) |
|
|
( ( HalpCharacterHeight - 1 ) & 0x1f ));
|
|
|
|
for ( RegisterIndex = CRT_HORIZONTAL_TOTAL;
|
|
RegisterIndex <= CRT_LINE_COMPARE; RegisterIndex++ ) {
|
|
|
|
VGA_CWRITE->CRTCAddress = (UCHAR)RegisterIndex;
|
|
VGA_CWRITE->CRTCData = CRTCSetup[RegisterIndex];
|
|
|
|
}
|
|
|
|
// Next setup the Graphics Controller registers. Straight from the
|
|
// table...
|
|
|
|
for ( RegisterIndex = GFX_SET_RESET; RegisterIndex <= GFX_BIT_MASK;
|
|
RegisterIndex++ ) {
|
|
|
|
VGA_CWRITE->GraphicsAddress = (UCHAR)RegisterIndex;
|
|
VGA_CWRITE->GraphicsData = GraphicsSetup[RegisterIndex];
|
|
|
|
}
|
|
|
|
// Next we need to setup the Attribute Controller registers. Instead
|
|
// of a separate Address and Data register, they are combined into a
|
|
// single register with its output directed by a two-state flip-flop.
|
|
// When the flip-flop is clear, the first write to the
|
|
// AttributeAddressAndData register is the index, and the second write
|
|
// is the data. In order to be sure the flip-flop is in a known state,
|
|
// we will clear it first by reading the InputStatus1 register...
|
|
|
|
for ( RegisterIndex = ATT_PALETTE_00; RegisterIndex <= ATT_COLOR_SELECT;
|
|
RegisterIndex++ ) {
|
|
|
|
Byte = VGA_CREAD->InputStatus1; // Reset flip-flop...
|
|
VGA_CWRITE->AttributeAddressAndData = (UCHAR)RegisterIndex;
|
|
KeStallExecutionProcessor(10);
|
|
VGA_CWRITE->AttributeAddressAndData = AttributeSetup[RegisterIndex];
|
|
KeStallExecutionProcessor(10);
|
|
VGA_CWRITE->AttributeAddressAndData = 0x20; // Return to normal mode
|
|
|
|
}
|
|
|
|
// Sequencer register setup, so return VGA to operation
|
|
VGA_CWRITE->SequencerAddress = SEQ_RESET;
|
|
VGA_CWRITE->SequencerData = NORMAL_OPERATION;
|
|
|
|
// Now that the Attribute and Color Palette registers are set up,
|
|
// now it is time to fill in the value into the Color registers.
|
|
// First initialize PEL Mask to FF as the BIOS would.
|
|
|
|
VGA_CWRITE->PELMask = 0xff;
|
|
VGA_CWRITE->PELAddressWriteMode = 0; // Set Index to 0...
|
|
|
|
for ( RegisterIndex = 0; RegisterIndex < 16; RegisterIndex++ ) {
|
|
for ( RGBIndex = 0; RGBIndex < 3; RGBIndex++ ) {
|
|
|
|
VGA_CWRITE->PELData = ColorValues[RegisterIndex][RGBIndex];
|
|
|
|
}
|
|
}
|
|
|
|
// Now we are ready to load the fonts into bit plane 2...
|
|
|
|
VGA_CWRITE->SequencerAddress = SEQ_MAP_MASK;
|
|
VGA_CWRITE->SequencerData = ENABLE_PLANE_2;
|
|
|
|
VGA_CWRITE->SequencerAddress = SEQ_MEMORY_MODE;
|
|
VGA_CWRITE->SequencerData = SEQUENTIAL_ADDRESSING | EXTENDED_MEMORY;
|
|
|
|
VGA_CWRITE->GraphicsAddress = GFX_MODE;
|
|
VGA_CWRITE->GraphicsData = WRITE_MODE_0;
|
|
|
|
VGA_CWRITE->GraphicsAddress = GFX_MISCELLANEOUS;
|
|
VGA_CWRITE->GraphicsData = MEMORY_MODE_1 | ALPHA_MODE;
|
|
|
|
// /**/VGA_CWRITE->GraphicsAddress = GFX_READ_MAP_SELECT;
|
|
// /**/VGA_CWRITE->GraphicsData = 0x2;
|
|
|
|
MemoryByte = FONT_MEMORY;
|
|
|
|
// Use font provided by OSLOADER...
|
|
for ( IndexI = 0; IndexI < 256; IndexI++ ) {
|
|
if (( IndexI < HalpFontHeader->FirstCharacter) ||
|
|
( IndexI > HalpFontHeader->LastCharacter )) {
|
|
Character = HalpFontHeader->DefaultCharacter;
|
|
} else {
|
|
Character = (UCHAR)IndexI;
|
|
}
|
|
Character -= HalpFontHeader->FirstCharacter;
|
|
FontData = ((PUCHAR)HalpFontHeader +
|
|
HalpFontHeader->Map[Character].Offset);
|
|
// Assumption, HalpCharacterHeight <= 16...
|
|
for ( IndexJ = 0; IndexJ < HalpCharacterHeight; IndexJ++ ) {
|
|
*MemoryByte = *FontData++;
|
|
MemoryByte++;
|
|
}
|
|
for ( IndexJ = HalpCharacterHeight; IndexJ < 32; IndexJ++ ) {
|
|
*MemoryByte = 0;
|
|
MemoryByte++;
|
|
}
|
|
}
|
|
|
|
|
|
// Now reload the default values into the above 4 registers...
|
|
|
|
VGA_CWRITE->SequencerAddress = SEQ_MAP_MASK;
|
|
VGA_CWRITE->SequencerData = SequencerSetup[SEQ_MAP_MASK];
|
|
|
|
VGA_CWRITE->SequencerAddress = SEQ_MEMORY_MODE;
|
|
VGA_CWRITE->SequencerData = SequencerSetup[SEQ_MEMORY_MODE];
|
|
|
|
VGA_CWRITE->GraphicsAddress = GFX_MODE;
|
|
VGA_CWRITE->GraphicsData = GraphicsSetup[GFX_MODE];
|
|
|
|
VGA_CWRITE->GraphicsAddress = GFX_MISCELLANEOUS;
|
|
VGA_CWRITE->GraphicsData = GraphicsSetup[GFX_MISCELLANEOUS];
|
|
|
|
// /**/VGA_CWRITE->GraphicsAddress = GFX_READ_MAP_SELECT;
|
|
// /**/VGA_CWRITE->GraphicsData = GraphicsSetup[GFX_READ_MAP_SELECT];
|
|
|
|
// Now set the screen to blue... For the attribute byte, the upper 4 bits
|
|
// are the background color, while the low 4 bits are the foreground
|
|
// color...
|
|
|
|
MemoryByte = VIDEO_MEMORY;
|
|
for ( IndexI = 0; IndexI < (HalpDisplayWidth*HalpDisplayText*2);
|
|
IndexI++ ) {
|
|
*MemoryByte++ = SPACE;
|
|
*MemoryByte++ = ( ( COLOR_BLUE << 4 ) | COLOR_INTENSE_WHITE );
|
|
}
|
|
|
|
HalpColumn = 0;
|
|
HalpRow = 0;
|
|
HalpDisplayOwnedByHal = TRUE;
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
HalDisplayString (
|
|
PUCHAR String
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine displays a character string on the display screen.
|
|
|
|
Arguments:
|
|
|
|
String - Supplies a pointer to the characters that are to be displayed.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
KIRQL OldIrql;
|
|
ENTRYLO SavedPte[MAX_PDE_PAGES];
|
|
ULONG PDECount;
|
|
|
|
//
|
|
// Raise IRQL to the highest level, flush the TB, and map the display
|
|
// frame buffer into the address space of the current process.
|
|
//
|
|
|
|
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
|
for ( PDECount = 0; PDECount < PDEPages[HalpDisplayType]; PDECount++ ) {
|
|
SavedPte[PDECount] = *((PENTRYLO)(PDE_BASE |
|
|
(((VideoMemoryVirtualBase[HalpDisplayType] +
|
|
(PDECount*0x400000))
|
|
>> (PDI_SHIFT - 2)) & 0xffc)));
|
|
}
|
|
KeFlushCurrentTb();
|
|
for ( PDECount = 0; PDECount < PDEPages[HalpDisplayType]; PDECount++ ) {
|
|
*((PENTRYLO)(PDE_BASE |
|
|
(((VideoMemoryVirtualBase[HalpDisplayType] +
|
|
(PDECount*0x400000))
|
|
>> (PDI_SHIFT - 2)) & 0xffc))) = HalpDisplayPte[PDECount];
|
|
}
|
|
|
|
//
|
|
// If ownership of the display has been switched to the system display
|
|
// driver, then reinitialize the display controller and revert ownership
|
|
// to the HAL.
|
|
//
|
|
|
|
if (HalpDisplayOwnedByHal == FALSE) {
|
|
HalpDisplayControllerSetup();
|
|
}
|
|
|
|
//
|
|
// Display characters until a null byte is encountered.
|
|
//
|
|
|
|
while (*String != 0) {
|
|
HalpDisplayCharacter(*String++);
|
|
}
|
|
|
|
//
|
|
// Restore the previous mapping for the current process, flush the TB,
|
|
// and lower IRQL to its previous level.
|
|
//
|
|
|
|
KeFlushCurrentTb();
|
|
for ( PDECount = 0; PDECount < PDEPages[HalpDisplayType]; PDECount++ ) {
|
|
*((PENTRYLO)(PDE_BASE | (((VideoMemoryVirtualBase[HalpDisplayType] +
|
|
(PDECount*0x400000))
|
|
>> (PDI_SHIFT - 2)) & 0xffc))) = SavedPte[PDECount];
|
|
}
|
|
KeLowerIrql(OldIrql);
|
|
|
|
return;
|
|
} /* end of HalpDisplayString() */
|
|
|
|
VOID
|
|
HalQueryDisplayParameters (
|
|
OUT PULONG WidthInCharacters,
|
|
OUT PULONG HeightInLines,
|
|
OUT PULONG CursorColumn,
|
|
OUT PULONG CursorRow
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine return information about the display area and current
|
|
cursor position.
|
|
|
|
Arguments:
|
|
|
|
WidthInCharacter - Supplies a pointer to a varible that receives
|
|
the width of the display area in characters.
|
|
|
|
HeightInLines - Supplies a pointer to a variable that receives the
|
|
height of the display area in lines.
|
|
|
|
CursorColumn - Supplies a pointer to a variable that receives the
|
|
current display column position.
|
|
|
|
CursorRow - Supplies a pointer to a variable that receives the
|
|
current display row position.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
//
|
|
// Set the display parameter values and return.
|
|
//
|
|
|
|
*WidthInCharacters = HalpDisplayWidth;
|
|
*HeightInLines = HalpDisplayText;
|
|
*CursorColumn = HalpColumn;
|
|
*CursorRow = HalpRow;
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
HalSetDisplayParameters (
|
|
IN ULONG CursorColumn,
|
|
IN ULONG CursorRow
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine set the current cursor position on the display area.
|
|
|
|
Arguments:
|
|
|
|
CursorColumn - Supplies the new display column position.
|
|
|
|
CursorRow - Supplies a the new display row position.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
//
|
|
// Set the display parameter values and return.
|
|
//
|
|
|
|
if (CursorColumn > HalpDisplayWidth) {
|
|
CursorColumn = HalpDisplayWidth;
|
|
}
|
|
|
|
if (CursorRow > HalpDisplayText) {
|
|
CursorRow = HalpDisplayText;
|
|
}
|
|
|
|
HalpColumn = CursorColumn;
|
|
HalpRow = CursorRow;
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
SlowMoveMemory (
|
|
OUT PUCHAR Destination,
|
|
IN PUCHAR Source,
|
|
IN ULONG Count
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is a slower memory move routine for the PG1280P.
|
|
Scrolling performance of the HAL is not that critical. This routine
|
|
can be replace with a hardware scroll assist routine at a later date
|
|
if it is deemed important.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG Index;
|
|
|
|
for ( Index = 0; Index < Count/4; Index++ ) {
|
|
*(PULONG)Destination = *(PULONG)Source;
|
|
Destination += 4;
|
|
Source += 4;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
HalpDisplayCharacter (
|
|
IN UCHAR Character
|
|
)
|
|
|
|
/*++
|
|
Routine Description:
|
|
|
|
This routine displays a character at the current x and y positions in
|
|
the frame buffer. If a newline is encounter, then the frame buffer is
|
|
scrolled. If characters extend below the end of line, then they are not
|
|
displayed.
|
|
|
|
Arguments:
|
|
|
|
Character - Supplies a character to be displayed.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
PUCHAR Destination;
|
|
ULONG Index;
|
|
|
|
//
|
|
// If the character is a newline, then scroll the screen up, blank the
|
|
// bottom line, and reset the x position.
|
|
//
|
|
|
|
if (Character == '\n') {
|
|
HalpColumn = 0;
|
|
if (HalpRow < (HalpDisplayText - 1)) {
|
|
HalpRow += 1;
|
|
|
|
} else {
|
|
// Scroll the screen one line
|
|
if ( IS_DISPLAY_PG1280 ) {
|
|
SlowMoveMemory((PVOID)VideoMemoryVirtualBase[HalpDisplayType],
|
|
(PVOID)(VideoMemoryVirtualBase[HalpDisplayType]
|
|
+ HalpScrollLine),
|
|
HalpScrollLength);
|
|
|
|
Destination = (PUCHAR)VideoMemoryVirtualBase[HalpDisplayType]
|
|
+ HalpScrollLength;
|
|
for (Index = 0; Index < HalpScrollLine/4; Index += 1) {
|
|
*(PULONG)Destination = PG1280_PALETTE_BLUE;
|
|
Destination+=4;
|
|
}
|
|
} else {
|
|
|
|
RtlMoveMemory((PVOID)VIDEO_MEMORY,
|
|
(PVOID)(VIDEO_MEMORY + HalpScrollLine),
|
|
HalpScrollLength);
|
|
|
|
Destination = (PUCHAR)VIDEO_MEMORY + HalpScrollLength;
|
|
for (Index = 0; Index < HalpScrollLine; Index += 2) {
|
|
*Destination++ = 0x20;
|
|
Destination++; // Skip attribute byte...
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
} else if (Character == '\r') {
|
|
HalpColumn = 0;
|
|
|
|
} else {
|
|
if ((Character < HalpFontHeader->FirstCharacter) ||
|
|
(Character > HalpFontHeader->LastCharacter)) {
|
|
Character = HalpFontHeader->DefaultCharacter;
|
|
}
|
|
|
|
//
|
|
// Note, this is done a bit different than the original Jazz HAL. Here, we
|
|
// pass the address of the Character itself. Since this HAL supports a
|
|
// character based VGA, and a bit-mapped based 24-bit card, passing a
|
|
// pointer to the character itself is easier and makes the following code
|
|
// a bit easier to understand.
|
|
//
|
|
|
|
// Original Jazz
|
|
// Character -= HalpFontHeader->FirstCharacter;
|
|
// HalpOutputCharacter((PUCHAR)HalpFontHeader + HalpFontHeader->Map[Character].Offset);
|
|
|
|
HalpOutputCharacter(&Character);
|
|
}
|
|
|
|
return;
|
|
|
|
} /* end of HalpDisplayCharacter() */
|
|
|
|
|
|
VOID
|
|
HalpOutputCharacter(
|
|
IN PUCHAR Glyph
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine insert a set of pixels into the display at the current x
|
|
cursor position. If the current x cursor position is at the end of the
|
|
line, then a newline is displayed before the specified character.
|
|
|
|
Arguments:
|
|
|
|
Character - Supplies a character to be displayed.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PUCHAR Destination, FontGlyph;
|
|
ULONG FontValue;
|
|
ULONG I;
|
|
ULONG J;
|
|
|
|
//
|
|
// If the current x cursor position is at the end of the line, then
|
|
// output a line feed before displaying the character.
|
|
//
|
|
|
|
if (HalpColumn == HalpDisplayWidth) {
|
|
HalpDisplayCharacter('\n');
|
|
}
|
|
|
|
//
|
|
// Output the specified character and update the x cursor position.
|
|
//
|
|
|
|
if ( IS_DISPLAY_PG1280 ) {
|
|
FontGlyph =
|
|
(PUCHAR)HalpFontHeader +
|
|
HalpFontHeader->Map[(*Glyph)-
|
|
HalpFontHeader->FirstCharacter].Offset;
|
|
Destination = (PUCHAR)(VIDEO_MEMORY +
|
|
(HalpRow * HalpScrollLine) +
|
|
(HalpColumn * HalpCharacterWidth * 4));
|
|
for (I = 0; I < HalpCharacterHeight; I += 1) {
|
|
FontValue = 0;
|
|
for (J = 0; J < HalpBytesPerRow; J += 1) {
|
|
FontValue |= *(FontGlyph + (J * HalpCharacterHeight)) << (24 - (J * 8));
|
|
}
|
|
|
|
FontGlyph += 1;
|
|
for (J = 0; J < HalpCharacterWidth ; J += 1) {
|
|
if ( FontValue >> 31 ) {
|
|
*(PULONG)Destination = PG1280_PALETTE_HI_WHITE;
|
|
}
|
|
Destination+=4;
|
|
FontValue <<= 1;
|
|
}
|
|
|
|
Destination +=
|
|
(8192 - ( HalpCharacterWidth * 4 ) );
|
|
}
|
|
|
|
} else {
|
|
Destination = (PUCHAR)(VIDEO_MEMORY +
|
|
(HalpRow * HalpScrollLine) + (HalpColumn*2));
|
|
*Destination = *Glyph;
|
|
|
|
}
|
|
|
|
HalpColumn += 1;
|
|
return;
|
|
}
|
|
|
|
#include "hm.h"
|
|
|
|
HW_DEVICE_EXTENSION MVHwDeviceExtension = { 0 };
|
|
PHW_DEVICE_EXTENSION pMVHwDeviceExtension = &MVHwDeviceExtension;
|
|
|
|
VOID
|
|
HalpDisplayPG1280Setup (
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine initializes the NeTpower NeTgraphics 1280 card on the
|
|
PICA bus.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
PULONG Buffer;
|
|
ULONG Limit, Index;
|
|
|
|
//
|
|
// Put display into 1024x768 @ 60Hz mode. This is the least common
|
|
// denominator for systems this card will be put in.
|
|
//
|
|
pMVHwDeviceExtension->iCurrentMode = 1;
|
|
HmInitHw( pMVHwDeviceExtension );
|
|
|
|
//
|
|
// Set the video memory to address color one.
|
|
//
|
|
|
|
Buffer = (PULONG)VIDEO_MEMORY;
|
|
Limit = ((8192 * 768) / sizeof(ULONG));
|
|
|
|
for (Index = 0; Index < Limit; Index += 1) {
|
|
*Buffer++ = PG1280_PALETTE_BLUE;
|
|
}
|
|
|
|
//
|
|
// Initialize the current display column, row, and ownership values.
|
|
//
|
|
|
|
HalpColumn = 0;
|
|
HalpRow = 0;
|
|
HalpDisplayOwnedByHal = TRUE;
|
|
return;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
**************************************************************************/
|
|
BOOLEAN HmInitHw
|
|
(
|
|
PHW_DEVICE_EXTENSION HwDeviceExtension
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine does hardware initializtion for Harley.
|
|
|
|
Arguments:
|
|
|
|
HwDeviceExtension - Supplies the miniport driver's adapter storage. This
|
|
storage is initialized to zero before this call.
|
|
|
|
Return Value:
|
|
|
|
This routine must return:
|
|
|
|
TRUE - Harley was initialized.
|
|
|
|
FALSE - Harley not initialized.
|
|
|
|
--*/
|
|
|
|
{
|
|
PHYSICAL_ADDRESS Address;
|
|
ULONG i;
|
|
|
|
//
|
|
// Map the framebuffer into the PICA virtual address space.
|
|
//
|
|
|
|
Address.HighPart = 0;
|
|
Address.LowPart = PEL_GFX1_PBASE;
|
|
HwDeviceExtension->fxVBase = (ULONG) VideoMemoryVirtualBase[PICA_PG1280];
|
|
|
|
i = HwDeviceExtension->iCurrentMode;
|
|
|
|
ProgramICD2062(HwDeviceExtension,
|
|
aMvpgModes[i].mvpgIcd2062.mClkData,
|
|
aMvpgModes[i].mvpgIcd2062.vClkData);
|
|
|
|
VideoTiming(HwDeviceExtension,
|
|
aMvpgModes[i].mvpgTimings.hBlankOn,
|
|
aMvpgModes[i].mvpgTimings.hBlankOff,
|
|
aMvpgModes[i].mvpgTimings.hSyncOn,
|
|
aMvpgModes[i].mvpgTimings.hSyncOff,
|
|
aMvpgModes[i].mvpgTimings.vBlankOn,
|
|
aMvpgModes[i].mvpgTimings.vBlankOff,
|
|
aMvpgModes[i].mvpgTimings.vSyncOn,
|
|
aMvpgModes[i].mvpgTimings.vSyncOff);
|
|
|
|
// program general config register in HUE
|
|
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) =
|
|
aMvpgModes[i].mvpgGeneralRegister;
|
|
|
|
// time delay to allow ECL clocks to fire up
|
|
// 1000 microseconds.
|
|
|
|
KeStallExecutionProcessor(1000);
|
|
|
|
/* program color ramps for DACs */
|
|
InitBT457(HwDeviceExtension);
|
|
ResetBT439(HwDeviceExtension);
|
|
|
|
*(PULONG)(HM_WRITEMASK + HwDeviceExtension->fxVBase) = 0xffffffff;
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
/***************************************************************************
|
|
* VideoTiming( hblankon, hblankoff, hsyncon, hsyncoff,
|
|
* vblankon, vblankoff, vsyncon, vsyncoff)
|
|
* This routine takes the monitor parameters (available from any
|
|
* monitor spec) and programs the video timing circuit appropriately.
|
|
***************************************************************************/
|
|
|
|
VOID VideoTiming
|
|
(
|
|
PHW_DEVICE_EXTENSION HwDeviceExtension,
|
|
ULONG hblankon,
|
|
ULONG hblankoff,
|
|
ULONG hsyncon,
|
|
ULONG hsyncoff,
|
|
ULONG vblankon,
|
|
ULONG vblankoff,
|
|
ULONG vsyncon,
|
|
ULONG vsyncoff
|
|
)
|
|
{
|
|
/* write them out to F2D */
|
|
|
|
((PULONG)(HM_VIDTIM + HwDeviceExtension->fxVBase))[0] = hblankon;
|
|
((PULONG)(HM_VIDTIM + HwDeviceExtension->fxVBase))[1] = hblankoff;
|
|
((PULONG)(HM_VIDTIM + HwDeviceExtension->fxVBase))[2] = hsyncon;
|
|
((PULONG)(HM_VIDTIM + HwDeviceExtension->fxVBase))[3] = hsyncoff;
|
|
((PULONG)(HM_VIDTIM + HwDeviceExtension->fxVBase))[4] = vblankon;
|
|
((PULONG)(HM_VIDTIM + HwDeviceExtension->fxVBase))[5] = vblankoff;
|
|
((PULONG)(HM_VIDTIM + HwDeviceExtension->fxVBase))[6] = vsyncon;
|
|
((PULONG)(HM_VIDTIM + HwDeviceExtension->fxVBase))[7] = vsyncoff;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
***************************************************************************/
|
|
VOID ResetBT439(PHW_DEVICE_EXTENSION HwDeviceExtension)
|
|
{
|
|
unsigned long old;
|
|
|
|
old = *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase);
|
|
old &= 0xfffffbff;
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) = old;
|
|
|
|
/* time delay for BT439 PLL sampling */
|
|
|
|
KeStallExecutionProcessor(1000);
|
|
|
|
old |= 0x00000400;
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) = old;
|
|
|
|
/* time delay for BT439 PLL sampling */
|
|
|
|
KeStallExecutionProcessor(1000);
|
|
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
***************************************************************************/
|
|
VOID Write_BT457
|
|
(
|
|
PHW_DEVICE_EXTENSION HwDeviceExtension,
|
|
ULONG addr,
|
|
ULONG value
|
|
)
|
|
{
|
|
((PULONG)(HM_BT457 + HwDeviceExtension->fxVBase))[addr] = value;
|
|
|
|
/* This delay might not be needed */
|
|
|
|
KeStallExecutionProcessor(1000);
|
|
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
* InitBT457() sets up the RAMDACs for 1280x1024, linear color ramp,
|
|
* no overlays (no cursor)
|
|
* Also resets the BT439 pipeline delay to 8 clocks
|
|
***************************************************************************/
|
|
VOID InitBT457(PHW_DEVICE_EXTENSION HwDeviceExtension)
|
|
{
|
|
unsigned long x, i, Bt457CmdReg;
|
|
|
|
/* BT457 control register initialization */
|
|
|
|
Write_BT457(HwDeviceExtension, 0, 0x040404); /* addr reg */
|
|
Write_BT457(HwDeviceExtension, 2, 0xFFFFFF); /* read mask reg */
|
|
Write_BT457(HwDeviceExtension, 0, 0x050505); /* addr reg */
|
|
Write_BT457(HwDeviceExtension, 2, 0x000000); /* blink mask reg */
|
|
Write_BT457(HwDeviceExtension, 0, 0x060606); /* addr reg */
|
|
|
|
i = HwDeviceExtension->iCurrentMode;
|
|
Bt457CmdReg = aMvpgModes[i].Bt457CommandReg;
|
|
|
|
Write_BT457(HwDeviceExtension, 2, Bt457CmdReg); /* command reg 1024 */
|
|
|
|
Write_BT457(HwDeviceExtension, 0, 0x070707); /* addr reg */
|
|
Write_BT457(HwDeviceExtension, 2, 0x010204); /* test reg */
|
|
|
|
/* BT457 color map initialization */
|
|
|
|
Write_BT457(HwDeviceExtension, 0, 0x000000); /* addr reg */
|
|
for (x=0; x < 256; x++)
|
|
{
|
|
Write_BT457(HwDeviceExtension, 1, x | (x << 8) | (x << 16)); /* RAM */
|
|
Write_BT457(HwDeviceExtension, 1, x | (x << 8) | (x << 16)); /* RAM */
|
|
Write_BT457(HwDeviceExtension, 1, x | (x << 8) | (x << 16)); /* RAM */
|
|
}
|
|
|
|
}
|
|
|
|
/***************************************************************************
|
|
* ProgramICD2062(mclkdata, vclkdata)
|
|
* program the ICD2062 programmable clock chip refresh clock (mclk) and
|
|
* video clock (vclk) using precalculated data.
|
|
***************************************************************************/
|
|
VOID ProgramICD2062
|
|
(
|
|
PHW_DEVICE_EXTENSION HwDeviceExtension,
|
|
ULONG mclkdata,
|
|
ULONG vclkdata
|
|
)
|
|
{
|
|
int k;
|
|
unsigned long j;
|
|
volatile unsigned long junk;
|
|
|
|
// /* REFRESH CLOCK */
|
|
/* OK. now perform the serial programming trick */
|
|
/* first do the unlock sequence */
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) |= G_SEL1; /* DATA = 1 */
|
|
FLUSHIO();
|
|
|
|
for (k=0; k < 10; k++)
|
|
{
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) |= G_SEL0;
|
|
FLUSHIO();
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL0;
|
|
FLUSHIO();
|
|
}
|
|
/* unlock */
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL1; /* DATA=0 */
|
|
FLUSHIO();
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) |= G_SEL0; /* CLK=1 */
|
|
FLUSHIO();
|
|
|
|
/* start bit */
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL1; /* DATA=0 */
|
|
FLUSHIO();
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL0; /* CLK=0 */
|
|
FLUSHIO();
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL1; /* DATA=0 */
|
|
FLUSHIO();
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) |= G_SEL0; /* CLK=1 */
|
|
FLUSHIO();
|
|
|
|
/* now clock in 24 bits of manchester encoded mclkdata */
|
|
for (k=0; k < 24; k++)
|
|
{
|
|
if ((mclkdata & 1) == 0)
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) |= G_SEL1; /* DATA=1 */
|
|
else
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL1; /* DATA=0 */
|
|
|
|
FLUSHIO();
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL0; /* CLK=0 */
|
|
FLUSHIO();
|
|
|
|
if ((mclkdata & 1) == 0)
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL1; /* DATA=0 */
|
|
else
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) |= G_SEL1; /* DATA=1 */
|
|
|
|
FLUSHIO();
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) |= G_SEL0; /* CLK=1 */
|
|
FLUSHIO();
|
|
mclkdata = mclkdata >> 1;
|
|
}
|
|
/* stop bit */
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) |= G_SEL1; /* DATA=1 */
|
|
FLUSHIO();
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL0; /* CLK=0 */
|
|
FLUSHIO();
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) |= G_SEL0; /* CLK=1 */
|
|
FLUSHIO();
|
|
|
|
/* select clock 0 */
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL0; /* CLK=0 */
|
|
FLUSHIO();
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL1; /* DATA=0 */
|
|
FLUSHIO();
|
|
|
|
/* delay at least 5ms */
|
|
for (j=0; j < 100000; j++)
|
|
junk = *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase);
|
|
|
|
/* VIDEO CLOCK */
|
|
|
|
/* OK. now perform the serial programming trick */
|
|
/* first do the unlock sequence */
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) |= G_SEL1; /* DATA = 1 */
|
|
FLUSHIO();
|
|
|
|
for (k=0; k < 10; k++)
|
|
{
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) |= G_SEL0;
|
|
FLUSHIO();
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL0;
|
|
FLUSHIO();
|
|
}
|
|
/* unlock */
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL1; /* DATA=0 */
|
|
FLUSHIO();
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) |= G_SEL0; /* CLK=1 */
|
|
FLUSHIO();
|
|
|
|
/* start bit */
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL1; /* DATA=0 */
|
|
FLUSHIO();
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL0; /* CLK=0 */
|
|
FLUSHIO();
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL1; /* DATA=0 */
|
|
FLUSHIO();
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) |= G_SEL0; /* CLK=1 */
|
|
FLUSHIO();
|
|
|
|
/* now clock in 24 bits of manchester encoded vclkdata */
|
|
for (k=0; k < 24; k++)
|
|
{
|
|
if ((vclkdata & 1) == 0)
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) |= G_SEL1; /* DATA=1 */
|
|
else
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL1; /* DATA=0 */
|
|
|
|
FLUSHIO();
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL0; /* CLK=0 */
|
|
FLUSHIO();
|
|
|
|
if ((vclkdata & 1) == 0)
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL1; /* DATA=0 */
|
|
else
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) |= G_SEL1; /* DATA=1 */
|
|
|
|
FLUSHIO();
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) |= G_SEL0; /* CLK=1 */
|
|
FLUSHIO();
|
|
vclkdata = vclkdata >> 1;
|
|
}
|
|
/* stop bit */
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) |= G_SEL1; /* DATA=1 */
|
|
FLUSHIO();
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL0; /* CLK=0 */
|
|
FLUSHIO();
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) |= G_SEL0; /* CLK=1 */
|
|
FLUSHIO();
|
|
|
|
/* select clock 0 */
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL0; /* CLK=0 */
|
|
FLUSHIO();
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) &= ~G_SEL1; /* DATA=0 */
|
|
FLUSHIO();
|
|
|
|
/* delay at least 5ms */
|
|
for (j=0; j < 100000; j++)
|
|
junk = *(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase);
|
|
}
|
|
|
|
VOID DevpResetVideo(PHW_DEVICE_EXTENSION HwDeviceExtension)
|
|
{
|
|
*(PULONG)(HM_GENERAL + HwDeviceExtension->fxVBase) |= G_VGAPASS;
|
|
}
|
|
|