windows-nt/Source/XPSP1/NT/drivers/video/ms/weitek/mini/viper.c
2020-09-26 16:20:57 +08:00

598 lines
12 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1993 Weitek Corporation
Module Name:
viper.c
Abstract:
This module contains OEM specific functions for the Diamond Viper
board.
Environment:
Kernel mode
Revision History may be found at the end of this file.
--*/
#include "p9.h"
#include "p9gbl.h"
#include "p9000.h"
#include "viper.h"
#include "vga.h"
#include "p9errlog.h"
#define REJECT_ON_BIOS_VERSION 0
//
// OEM specific static data.
//
//
// This structure is used to match the possible physical address
// mappings with the value to be written to the sequencer control
// register.
typedef struct
{
PHYSICAL_ADDRESS BaseMemAddr;
USHORT RegValue;
} MEM_RANGE;
MEM_RANGE ViperMemRange[] =
{
{ 0x0A0000000, 0L, MEM_AXXX },
{ 0x080000000, 0L, MEM_8XXX },
{ 0x020000000, 0L, MEM_2XXX },
{ 0x01D000000, 0L, MEM_AXXX }
};
LONG NumMemRanges = sizeof(ViperMemRange) / sizeof(MEM_RANGE);
#ifdef REJECT_ON_BIOS_VERSION
/*++
** bRejectOnBiosVersion
*
* FILENAME: D:\nt351.nc\weitek\p9x\mini\viper.c
*
* PARAMETERS: PHW_DEVICE_EXTENSION HwDeviceExtension
* PUCHAR pjBios linear address of the BIOS
* ULONG ulBiosLength lengh of the BIOS
*
* DESCRIPTION: Scan the Bios,
*
* RETURNS: TRUE to reject supporting this card.
* FALSE to support this card.
*
*
--*/
BOOLEAN
bRejectOnBiosVersion(
PHW_DEVICE_EXTENSION HwDeviceExtension,
PUCHAR pjBiosAddr,
ULONG ulBiosLength)
{
// Add the strings you want to detect for rejection to this array
static PUCHAR aszBiosVersion[] = {
"VIPER VLB Vers. 1",
"VIPER VLB Vers. 2",
NULL
};
LONG i;
BOOLEAN bFound = FALSE;
for (i = 0; aszBiosVersion[i] != 0; i++)
{
if (VideoPortScanRom(HwDeviceExtension,
(PUCHAR) pjBiosAddr,
VGA_BIOS_LEN,
aszBiosVersion[i]))
{
bFound = TRUE;
break;
}
}
if (bFound == TRUE)
{
VideoPortLogError(HwDeviceExtension,
NULL,
P9_DOWN_LEVEL_BIOS,
i);
VideoDebugPrint((1, "P9X - Down Level Bios\n"));
}
// We will always boot, we'll just warn the user that bad things may happen
return (FALSE);
}
#endif // REJECT_ON_BIOS_VERSION
#define P9001_REV_ID 0x08
BOOLEAN
ViperGetBaseAddr(
PHW_DEVICE_EXTENSION HwDeviceExtension
)
/*++
Routine Description:
Perform board detection and if present return the P9000 base address.
Arguments:
HwDeviceExtension - Pointer to the miniport driver's device extension.
Return Value:
TRUE - Board found, P9 and Frame buffer address info was placed in
the device extension.
FALSE - Board not found.
--*/
{
VP_STATUS status;
SHORT i;
PUCHAR pucBiosAddr;
BOOLEAN bValid = FALSE;
ULONG ulTemp;
VIDEO_ACCESS_RANGE BiosAccessRange =
{
VGA_BIOS_ADDR, // Low address
0x00000000, // Hi address
VGA_BIOS_LEN, // length
0, // Is range in i/o space?
1, // Range should be visible
1 // Range should be shareable
};
if (HwDeviceExtension->MachineType == SIEMENS_P9100_VLB)
return FALSE;
//
// More PnP goofing around: Try to detect a PCI card here. If successful,
// fail finding a VLB Viper, since we won't support both a PCI and VLB
// viper on the same machine as of NT5. We love PnP.
//
if (VideoPortGetBusData(HwDeviceExtension,
PCIConfiguration,
HwDeviceExtension->PciSlotNum,
&ulTemp, //bogus name
P9001_REV_ID,
sizeof(ulTemp)))
{
VideoDebugPrint((1, "VPGetBusData succeeded???, line %d\n", __LINE__));
return(FALSE);
}
//
// Determine if a Viper card is installed by scanning the VGA BIOS ROM
// memory space.
//
//
// Map in the BIOS' memory space. If it can't be mapped,
// return an error.
//
if (HwDeviceExtension->MachineType == SIEMENS)
{
BiosAccessRange.RangeStart.LowPart += 0x10000000L;
}
if (VideoPortVerifyAccessRanges(HwDeviceExtension,
1,
&BiosAccessRange) != NO_ERROR)
{
return(FALSE);
}
if ((pucBiosAddr =
VideoPortGetDeviceBase(HwDeviceExtension,
BiosAccessRange.RangeStart,
BiosAccessRange.RangeLength,
FALSE)) == 0)
{
return(FALSE);
}
if (!VideoPortScanRom(HwDeviceExtension,
pucBiosAddr,
VGA_BIOS_LEN,
VIPER_VL_ID_STR))
{
VideoPortFreeDeviceBase(HwDeviceExtension, pucBiosAddr);
return(FALSE);
}
#ifdef REJECT_ON_BIOS_VERSION
if (bRejectOnBiosVersion(HwDeviceExtension, pucBiosAddr, VGA_BIOS_LEN))
return (FALSE);
#endif // REJECT_ON_BIOS_VERSION
VideoPortFreeDeviceBase(HwDeviceExtension, pucBiosAddr);
//
// For now, pretend we have a Weitek 5x86 VGA. Later we may call the
// Viper BIOS to determine which type of BIOS is installed.
//
HwDeviceExtension->AdapterDesc.bWtk5x86 = TRUE;
//
// Copy the DAC register access ranges to the global access range
// structure.
//
VideoPortMoveMemory(&DriverAccessRanges[NUM_DRIVER_ACCESS_RANGES],
VLDefDACRegRange,
HwDeviceExtension->Dac.cDacRegs *
sizeof(VIDEO_ACCESS_RANGE));
//
// A value for the P9 base address may have beens found in the registry,
// and it is now stored in the device extension. Ensure the address
// value is valid for the Viper card. Then use it to compute
// the starting address of the P9000 registers and frame buffer,
// and store it in the device extension.
//
for (i = 0; i < NumMemRanges; i++)
{
if (HwDeviceExtension->P9PhysAddr.LowPart ==
ViperMemRange[i].BaseMemAddr.LowPart)
{
bValid = TRUE;
break;
}
}
//
// If the address value is invalid, or was not found in the registry,
// use the default.
//
if (!bValid)
{
HwDeviceExtension->P9PhysAddr.LowPart = MemBase;
}
return(TRUE);
}
VOID
ViperEnableP9(
PHW_DEVICE_EXTENSION HwDeviceExtension
)
/*++
Routine Description:
Perform the OEM specific tasks necessary to enable the P9000. These
include memory mapping, setting the sync polarities, and enabling the
P9000 video output.
Arguments:
HwDeviceExtension - Pointer to the miniport driver's device extension.
Return Value:
None.
--*/
{
USHORT holdit;
//
// Select external frequency.
//
VGA_WR_REG(MISCOUT, VGA_RD_REG(MISCIN) | (MISCD | MISCC));
//
// If this is a Weitek VGA, unlock it.
//
if (HwDeviceExtension->AdapterDesc.bWtk5x86)
{
UnlockVGARegs(HwDeviceExtension);
}
VGA_WR_REG(SEQ_INDEX_PORT, SEQ_OUTCNTL_INDEX);
holdit = VGA_RD_REG(SEQ_DATA_PORT);
//
// Set the sync polarity. First clear the sync polarity bits.
//
holdit &= ~POL_MASK;
//
// Viper controls h and v sync polarities independently. Set the
// vertical sync polarity.
//
if (HwDeviceExtension->VideoData.vp == POSITIVE)
{
holdit |= VSYNC_POL_MASK;
}
//
// Disable VGA video output.
//
holdit &= VGA_VIDEO_DIS;
if (HwDeviceExtension->VideoData.hp == POSITIVE)
{
holdit |= HSYNC_POL_MASK;
}
holdit |= P9_VIDEO_ENB;
VGA_WR_REG(SEQ_DATA_PORT, holdit);
//
// If this is a Weitek VGA, lock it.
//
if (HwDeviceExtension->AdapterDesc.bWtk5x86)
{
LockVGARegs(HwDeviceExtension);
}
return;
}
BOOLEAN
ViperDisableP9(
PHW_DEVICE_EXTENSION HwDeviceExtension
)
/*++
Routine Description:
Arguments:
HwDeviceExtension - Pointer to the miniport driver's device extension.
pPal - Pointer to the array of pallete entries.
StartIndex - Specifies the first pallete entry provided in pPal.
Count - Number of palette entries in pPal
Return Value:
TRUE, indicating *no* int10 is needed to complete the switch
--*/
{
USHORT holdit;
//
// If this is a Weitek VGA, unlock it.
//
if (HwDeviceExtension->AdapterDesc.bWtk5x86)
{
UnlockVGARegs(HwDeviceExtension);
}
VGA_WR_REG(SEQ_INDEX_PORT, SEQ_OUTCNTL_INDEX);
holdit = VGA_RD_REG(SEQ_DATA_PORT);
//
// Disable P9000 video output.
//
holdit &= P9_VIDEO_DIS;
//
// VGA output enable is a seperate register bit for the Viper board.
//
holdit |= VGA_VIDEO_ENB;
VGA_WR_REG(SEQ_INDEX_PORT, SEQ_OUTCNTL_INDEX);
VGA_WR_REG(SEQ_DATA_PORT, holdit);
//
// Restore clock select bits.
//
VGA_WR_REG(MISCOUT, HwDeviceExtension->MiscRegState);
//
// If this is a Weitek VGA, lock it.
//
if (HwDeviceExtension->AdapterDesc.bWtk5x86)
{
LockVGARegs(HwDeviceExtension);
}
return TRUE;
}
BOOLEAN
ViperEnableMem(
PHW_DEVICE_EXTENSION HwDeviceExtension
)
/*++
Routine Description:
Enables the P9000 memory at the physical base address stored in the
device extension.
Arguments:
HwDeviceExtension - Pointer to the miniport driver's device extension.
Return Value:
None.
--*/
{
USHORT holdit;
SHORT i;
//
// If this is a Weitek VGA, unlock it.
//
if (HwDeviceExtension->AdapterDesc.bWtk5x86)
{
UnlockVGARegs(HwDeviceExtension);
}
//
// Read the contents of the sequencer memory address register.
//
VGA_WR_REG(SEQ_INDEX_PORT, SEQ_OUTCNTL_INDEX);
holdit = VGA_RD_REG(SEQ_DATA_PORT);
//
// Clear out any address bits which are set.
//
holdit &= ADDR_SLCT_MASK;
//
// Map the P9000 to the address specified in the device extension.
//
for (i = 0; i < NumMemRanges; i++ )
{
if (ViperMemRange[i].BaseMemAddr.LowPart ==
HwDeviceExtension->P9PhysAddr.LowPart)
{
holdit |= ViperMemRange[i].RegValue;
break;
}
}
VGA_WR_REG(SEQ_DATA_PORT, holdit);
//
// If this is a Weitek VGA, lock it.
//
if (HwDeviceExtension->AdapterDesc.bWtk5x86)
{
LockVGARegs(HwDeviceExtension);
}
return(TRUE);
}
VOID
ViperSetMode(
PHW_DEVICE_EXTENSION HwDeviceExtension
)
/*++
Routine Description:
This routine sets the video mode. Different OEM adapter implementations
require that initialization operations be performed in a certain
order. This routine uses the standard order which addresses most
implementations (Viper VL and VIPER PCI).
Arguments:
HwDeviceExtension - Pointer to the miniport driver's device extension.
Return Value:
None.
--*/
{
//
// Save the value in the VGA's Misc Output register.
//
HwDeviceExtension->MiscRegState = VGA_RD_REG(MISCIN);
//
// Enable the Vipers Memory Map.
//
HwDeviceExtension->AdapterDesc.P9EnableMem(HwDeviceExtension);
//
// Enable P9000 video.
//
HwDeviceExtension->AdapterDesc.P9EnableVideo(HwDeviceExtension);
//
// Initialize the DAC.
//
HwDeviceExtension->Dac.DACInit(HwDeviceExtension);
//
// Set the dot clock.
//
DevSetClock(HwDeviceExtension,
(USHORT) HwDeviceExtension->VideoData.dotfreq1,
FALSE,
TRUE);
//
// If this mode uses the palette, clear it to all 0s.
//
if (P9Modes[HwDeviceExtension->CurrentModeNumber].modeInformation.AttributeFlags
&& VIDEO_MODE_PALETTE_DRIVEN)
{
HwDeviceExtension->Dac.DACClearPalette(HwDeviceExtension);
}
}