windows-nt/Source/XPSP1/NT/drivers/video/ms/weitek/mini/pci.c

1252 lines
42 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1993 Weitek Corporation
Module Name:
pci.c
Abstract:
This module contains PCI code for the Weitek P9 miniport device driver.
Environment:
Kernel mode
Revision History may be found at the end of this file.
--*/
#include "p9.h"
#include "p9gbl.h"
#include "p9000.h"
#include "pci.h"
#include "vga.h"
#include "p91regs.h"
//
// OEM specific static data.
//
extern VOID
VLSetModeP91(
PHW_DEVICE_EXTENSION HwDeviceExtension
);
extern VOID VLEnableP91(
PHW_DEVICE_EXTENSION HwDeviceExtension
);
VIDEO_ACCESS_RANGE Pci9001DefDACRegRange[] =
{
{
RS_0_PCI_9001_ADDR, // Low address
0x00000000, // Hi address
0x01, // length
1, // Is range in i/o space?
1, // Range should be visible
1 // Range should be shareable
},
{
RS_1_PCI_9001_ADDR, // Low address
0x00000000, // Hi address
0x01, // length
1, // Is range in i/o space?
1, // Range should be visible
1 // Range should be shareable
},
{
RS_2_PCI_9001_ADDR, // Low address
0x00000000, // Hi address
0x01, // length
1, // Is range in i/o space?
1, // Range should be visible
1 // Range should be shareable
},
{
RS_3_PCI_9001_ADDR, // Low address
0x00000000, // Hi address
0x01, // length
1, // Is range in i/o space?
1, // Range should be visible
1 // Range should be shareable
},
{
RS_4_PCI_9001_ADDR, // Low address
0x00000000, // Hi address
0x01, // length
1, // Is range in i/o space?
1, // Range should be visible
1 // Range should be shareable
},
{
RS_5_PCI_9001_ADDR, // Low address
0x00000000, // Hi address
0x01, // length
1, // Is range in i/o space?
1, // Range should be visible
1 // Range should be shareable
},
{
RS_6_PCI_9001_ADDR, // Low address
0x00000000, // Hi address
0x01, // length
1, // Is range in i/o space?
1, // Range should be visible
1 // Range should be shareable
},
{
RS_7_PCI_9001_ADDR, // Low address
0x00000000, // Hi address
0x01, // length
1, // Is range in i/o space?
1, // Range should be visible
1 // Range should be shareable
},
{
RS_8_PCI_9001_ADDR, // Low address
0x00000000, // Hi address
0x01, // length
1, // Is range in i/o space?
1, // Range should be visible
1 // Range should be shareable
},
{
RS_9_PCI_9001_ADDR, // Low address
0x00000000, // Hi address
0x01, // length
1, // Is range in i/o space?
1, // Range should be visible
1 // Range should be shareable
},
{
RS_A_PCI_9001_ADDR, // Low address
0x00000000, // Hi address
0x01, // length
1, // Is range in i/o space?
1, // Range should be visible
1 // Range should be shareable
},
{
RS_B_PCI_9001_ADDR, // Low address
0x00000000, // Hi address
0x01, // length
1, // Is range in i/o space?
1, // Range should be visible
1 // Range should be shareable
},
{
RS_C_PCI_9001_ADDR, // Low address
0x00000000, // Hi address
0x01, // length
1, // Is range in i/o space?
1, // Range should be visible
1 // Range should be shareable
},
{
RS_D_PCI_9001_ADDR, // Low address
0x00000000, // Hi address
0x01, // length
1, // Is range in i/o space?
1, // Range should be visible
1 // Range should be shareable
},
{
RS_E_PCI_9001_ADDR, // Low address
0x00000000, // Hi address
0x01, // length
1, // Is range in i/o space?
1, // Range should be visible
1 // Range should be shareable
},
{
RS_F_PCI_9001_ADDR, // Low address
0x00000000, // Hi address
0x01, // length
1, // Is range in i/o space?
1, // Range should be visible
1 // Range should be shareable
}
};
VIDEO_ACCESS_RANGE Pci9002DefDACRegRange[] =
{
{
RS_0_PCI_9002_ADDR, // Low address
0x00000000, // Hi address
0x01, // length
1, // Is range in i/o space?
1, // Range should be visible
1 // Range should be shareable
},
{
RS_1_PCI_9002_ADDR, // Low address
0x00000000, // Hi address
0x01, // length
1, // Is range in i/o space?
1, // Range should be visible
1 // Range should be shareable
},
{
RS_2_PCI_9002_ADDR, // Low address
0x00000000, // Hi address
0x01, // length
1, // Is range in i/o space?
1, // Range should be visible
1 // Range should be shareable
},
{
RS_3_PCI_9002_ADDR, // Low address
0x00000000, // Hi address
0x01, // length
1, // Is range in i/o space?
1, // Range should be visible
1 // Range should be shareable
},
{
RS_4_PCI_9002_ADDR, // Low address
0x00000000, // Hi address
0x01, // length
1, // Is range in i/o space?
1, // Range should be visible
1 // Range should be shareable
},
{
RS_5_PCI_9002_ADDR, // Low address
0x00000000, // Hi address
0x01, // length
1, // Is range in i/o space?
1, // Range should be visible
1 // Range should be shareable
},
{
RS_6_PCI_9002_ADDR, // Low address
0x00000000, // Hi address
0x01, // length
1, // Is range in i/o space?
1, // Range should be visible
1 // Range should be shareable
},
{
RS_7_PCI_9002_ADDR, // Low address
0x00000000, // Hi address
0x01, // length
1, // Is range in i/o space?
1, // Range should be visible
1 // Range should be shareable
},
{
RS_8_PCI_9002_ADDR, // Low address
0x00000000, // Hi address
0x01, // length
1, // Is range in i/o space?
1, // Range should be visible
1 // Range should be shareable
},
{
RS_9_PCI_9002_ADDR, // Low address
0x00000000, // Hi address
0x01, // length
1, // Is range in i/o space?
1, // Range should be visible
1 // Range should be shareable
},
{
RS_A_PCI_9002_ADDR, // Low address
0x00000000, // Hi address
0x01, // length
1, // Is range in i/o space?
1, // Range should be visible
1 // Range should be shareable
},
{
RS_B_PCI_9002_ADDR, // Low address
0x00000000, // Hi address
0x01, // length
1, // Is range in i/o space?
1, // Range should be visible
1 // Range should be shareable
},
{
RS_C_PCI_9002_ADDR, // Low address
0x00000000, // Hi address
0x01, // length
1, // Is range in i/o space?
1, // Range should be visible
1 // Range should be shareable
},
{
RS_D_PCI_9002_ADDR, // Low address
0x00000000, // Hi address
0x01, // length
1, // Is range in i/o space?
1, // Range should be visible
1 // Range should be shareable
},
{
RS_E_PCI_9002_ADDR, // Low address
0x00000000, // Hi address
0x01, // length
1, // Is range in i/o space?
1, // Range should be visible
1 // Range should be shareable
},
{
RS_F_PCI_9002_ADDR, // Low address
0x00000000, // Hi address
0x01, // length
1, // Is range in i/o space?
1, // Range should be visible
1 // Range should be shareable
}
};
/******************************************************************************
** bIntergraphBoard
*
* PARAMETERS: HwDeviceExtension
*
* DESCRIPTION: Determine if we're trying to init an Intergraph Board
*
* RETURNS: TRUE - if this is an Intergraph Board
* FALSE - if this is not an Intergraph Board
*
* CREATED: 02/20/95 13:33:23
*
* BY: c-jeffn
*
* copyright (c) 1995, Newman Consulting
*
******************************************************************************/
BOOLEAN
bIntergraphBoard(
PHW_DEVICE_EXTENSION HwDeviceExtension
)
{
ULONG ulRet;
UCHAR jConfig66, jOEMId, *pjOEMId;
VP_STATUS vpStatus;
VIDEO_ACCESS_RANGE AccessRange;
BOOLEAN bRet;
VideoDebugPrint((2, "P9!bIntergraphBoard - Entry\n"));
// Note that the P9100 must be in native mode before this function
// is called.
bRet = FALSE;
// Test to see if the P9100 indicates external io device is there
// If not, can't be Intergraph board
if ( (HwDeviceExtension->p91State.ulPuConfig & P91_PUC_EXT_IO) == 0 )
goto exit;
// Set Bit 4 of Config 66. This will allow access to the Intergraph
// Specific registers.
jConfig66 = 0x10;
ulRet = VideoPortSetBusData(HwDeviceExtension,
PCIConfiguration,
HwDeviceExtension->PciSlotNum,
&jConfig66,
0x42,
sizeof (UCHAR));
if (ulRet != 1)
{
VideoDebugPrint((2, "P9!bIntergraphBoard - failed VideoPortSetBusData\n"));
VideoDebugPrint((2, "\tulRet: %x\n", ulRet));
goto exit;
}
// Check P9100 register 0x208 for ID in native mode
ulRet = P9_RD_REG(P91_EXT_IO_ID); // Get the external io id value
jOEMId = (UCHAR)(ulRet >> 16); // per Weitek programmer's manual
if (jOEMId == 0xFE) // This is the id assigned to Intergraph
bRet = TRUE;
// Need to reset Config register 66 bit 4.
jConfig66 = 0x00;
ulRet = VideoPortSetBusData(HwDeviceExtension,
PCIConfiguration,
HwDeviceExtension->PciSlotNum,
&jConfig66,
0x42,
sizeof (UCHAR));
exit:
VideoDebugPrint((2, "P9!bIntergraphBoard - Exit: %x\n", bRet));
return (bRet);
}
//
// this thing was 0. PNP forces fix since the system now put the IO
// resources at index 1 in the VIDEO_ACCESS_RANGE returned via
// VideoPortGetAccessRanges().
//
#define IO_ACCESS_INDEX 1
#define VGABIOS_ACCESS_INDEX 2
BOOLEAN
PciGetBaseAddr(
PHW_DEVICE_EXTENSION HwDeviceExtension
)
/*++
Routine Description:
Perform board detection and if present return the P9 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. PCI extended base address was placed in the
device extension.
FALSE - Board not found.
--*/
{
VIDEO_ACCESS_RANGE PciAccessRange[3];
PVIDEO_ACCESS_RANGE DefaultDACRegRange;
ULONG ulTempAddr;
PUCHAR pucBiosAddr;
PUCHAR pucBoardAddr;
ULONG ulTemp;
LONG i;
VP_STATUS status;
ULONG wcpID;
VideoPortZeroMemory(PciAccessRange, 3 * sizeof(VIDEO_ACCESS_RANGE));
VideoDebugPrint((2, "PciGetbaseAddr() ENTRY\n"));
//
// Only the viper p9000 works on the Siemens boxes
//
if (HwDeviceExtension->MachineType == SIEMENS
|| HwDeviceExtension->MachineType == SIEMENS_P9100_VLB)
{
VideoDebugPrint((1, "PciGetbaseAddr() Failed, line %d\n", __LINE__));
return FALSE;
}
//
// See if the PCI HAL can locate a Weitek 9001 PCI Board.
//
//
// First check for a P9100
//
if (PciFindDevice(HwDeviceExtension,
WTK_9100_ID,
WTK_VENDOR_ID,
&HwDeviceExtension->PciSlotNum))
{
wcpID = P9100_ID;
HwDeviceExtension->usBusType = PCI;
// Just a hack to get things working.
// NOTE: !!! WE should really do the detection.
HwDeviceExtension->p91State.bVideoPowerEnabled = FALSE;
// Now make sure we are looking for a P9100, if were not
// then fail.
if (HwDeviceExtension->P9CoprocInfo.CoprocId != P9100_ID)
{
VideoDebugPrint((1, "Not a 9100, even though PCIFindDevice() thinks it is\n"));
return(FALSE);
}
#ifdef _MIPS_
//
// SNI platform recognition and specific stuff
//
{
extern VP_STATUS GetCPUIdCallback(
PVOID HwDeviceExtension,
PVOID Context,
VIDEO_DEVICE_DATA_TYPE DeviceDataType,
PVOID Identifier,
ULONG IdentifierLength,
PVOID ConfigurationData,
ULONG ConfigurationDataLength,
PVOID ComponentInformation,
ULONG ComponentInformationLength
);
if(VideoPortIsCpu(L"RM200PCI")
|| VideoPortIsCpu(L"RM300PCI")
|| VideoPortIsCpu(L"RM300PCI MP")
|| VideoPortIsCpu(L"RM400PCI")
|| VideoPortIsCpu(L"RM4x0PCI"))
{
// adjust the VGA physical address with the E/ISA I/O space
DriverAccessRanges[1].RangeStart.LowPart += 0x14000000 ;
HwDeviceExtension->MachineType = SIEMENS_P9100_PCi;
}
}
#endif
}
else if (PciFindDevice(HwDeviceExtension,
WTK_9001_ID,
WTK_VENDOR_ID,
&HwDeviceExtension->PciSlotNum))
{
wcpID = P9000_ID;
// Now make sure we are looking for a P9000, if were not
// then fail.
if (HwDeviceExtension->P9CoprocInfo.CoprocId != P9000_ID)
{
VideoDebugPrint((1, "PciGetbaseAddr() Failed !P9000, line %d\n", __LINE__));
return(FALSE);
}
VideoDebugPrint((2, "PciGetbaseAddr() This is a P900X\n"));
//
// Read the config space to determine if
// this is Rev 1 or 2. This will determine at which addresses
// the DAC registers are mapped.
//
if (!VideoPortGetBusData(HwDeviceExtension,
PCIConfiguration,
HwDeviceExtension->PciSlotNum,
&ulTemp,
P9001_REV_ID,
sizeof(ulTemp)))
{
VideoDebugPrint((1, "PciGetbaseAddr() Failed, DAC weirdness, line %d\n", __LINE__));
return(FALSE);
}
//
// Got the 9001 rev id. Choose the appropriate table of DAC register
// addresses.
//
switch((UCHAR) (ulTemp))
{
case 1 :
VideoDebugPrint((2, "PciGetbaseAddr(), DAC id is 1\n"));
//
// This is a Rev 1 9001, which uses the standard VL DAC
// Addresses. All known rev 1 implementations use the
// Weitek 5286 VGA chip.
//
DefaultDACRegRange = VLDefDACRegRange;
HwDeviceExtension->AdapterDesc.bWtk5x86 = TRUE;
break;
case 2 :
default:
VideoDebugPrint((2, "PciGetbaseAddr(), DAC id is 2 or default\n"));
//
// This is a Rev 2 9001. Set up the table of DAC register
// offsets accordingly.
//
DefaultDACRegRange = Pci9001DefDACRegRange;
//
// A Rev 2 9001 is present. Get the BIOS ROM address from the
// PCI configuration space so we can do a ROM scan to
// determine if this is a Viper PCI adapter.
//
PciAccessRange[IO_ACCESS_INDEX].RangeStart.LowPart = 0;
PciAccessRange[IO_ACCESS_INDEX].RangeStart.HighPart = 0;
if (VideoPortGetBusData(HwDeviceExtension,
PCIConfiguration,
HwDeviceExtension->PciSlotNum,
&PciAccessRange[IO_ACCESS_INDEX].RangeStart.LowPart,
P9001_BIOS_BASE_ADDR,
sizeof(ULONG)) == 0)
{
VideoDebugPrint((1, "PciGetbaseAddr() Failed. ROM bios not P9001, line %d\n", __LINE__));
return FALSE;
}
if (PciAccessRange[IO_ACCESS_INDEX].RangeStart.LowPart)
{
//
// We found an address for the BIOS. Verify it.
//
// Set up the access range so we can map out the BIOS ROM
// space. This will allow us to scan the ROM and detect the
// presence of a Viper PCI adapter.
//
PciAccessRange[IO_ACCESS_INDEX].RangeInIoSpace = FALSE;
PciAccessRange[IO_ACCESS_INDEX].RangeVisible = TRUE;
PciAccessRange[IO_ACCESS_INDEX].RangeShareable = TRUE;
PciAccessRange[IO_ACCESS_INDEX].RangeLength = 0x1000;
//
// Check to see if another miniport driver has allocated the
// BIOS' memory space.
//
if (VideoPortVerifyAccessRanges(HwDeviceExtension,
1L,
PciAccessRange) != NO_ERROR)
{
PciAccessRange[IO_ACCESS_INDEX].RangeStart.LowPart = 0;
}
}
if (PciAccessRange[IO_ACCESS_INDEX].RangeStart.LowPart == 0)
{
status = VideoPortGetAccessRanges(HwDeviceExtension,
0,
NULL,
3,
PciAccessRange,
NULL,
NULL,
&HwDeviceExtension->PciSlotNum);
if (status != NO_ERROR)
{
VideoDebugPrint((1, "PciGetbaseAddr() Failed, GetAccessRanges(), line %d, status:%x\n", __LINE__, status));
return(FALSE);
}
}
//
// Map in the BIOS' memory space. If it can't be mapped,
// return an error.
//
PciAccessRange[VGABIOS_ACCESS_INDEX].RangeStart.LowPart = 0xC0000;
PciAccessRange[VGABIOS_ACCESS_INDEX].RangeStart.HighPart = 0x0000;
PciAccessRange[VGABIOS_ACCESS_INDEX].RangeLength = BIOS_RANGE_LEN;
PciAccessRange[VGABIOS_ACCESS_INDEX].RangeInIoSpace = FALSE;
VideoDebugPrint((1, "PciGetbaseAddr() about to get BIOS address, line %d, status:%x\n", __LINE__, status));
if ((pucBiosAddr =
VideoPortGetDeviceBase(HwDeviceExtension,
PciAccessRange[VGABIOS_ACCESS_INDEX].RangeStart,
PciAccessRange[VGABIOS_ACCESS_INDEX].RangeLength,
PciAccessRange[VGABIOS_ACCESS_INDEX].RangeInIoSpace)) == 0)
{
VideoDebugPrint((1, "PciGetbaseAddr() Failed on VGA bios, line %d\n", __LINE__));
return(FALSE);
}
//
// Enable the Adapter BIOS.
//
ulTemp = PciAccessRange[VGABIOS_ACCESS_INDEX].RangeStart.LowPart | PCI_BIOS_ENB;
VideoDebugPrint((1, "PciGetbaseAddr() about to enable bios, line %d, status:%x\n", __LINE__, status));
VideoPortSetBusData(HwDeviceExtension,
PCIConfiguration,
HwDeviceExtension->PciSlotNum,
&ulTemp,
P9001_BIOS_BASE_ADDR,
sizeof(ULONG));
VideoDebugPrint((1, "PciGetbaseAddr() about to scan rom, line %d, status:%x\n", __LINE__, status));
if (VideoPortScanRom(HwDeviceExtension,
pucBiosAddr,
BIOS_RANGE_LEN,
VIPER_ID_STR))
{
//
// A Viper PCI is present, use the Viper set mode,
// enable/disable video function pointers, and clk
// divisor values. Also, Viper PCI does not
// use a Weitek VGA.
//
HwDeviceExtension->AdapterDesc.OEMSetMode = ViperSetMode;
HwDeviceExtension->AdapterDesc.P9EnableVideo =
ViperPciP9Enable;
HwDeviceExtension->AdapterDesc.P9DisableVideo =
ViperPciP9Disable;
HwDeviceExtension->AdapterDesc.iClkDiv = 4;
HwDeviceExtension->AdapterDesc.bWtk5x86 = FALSE;
}
else
{
//
// All non-Viper Rev 2 implementations use a Weitek
// 5286 VGA chip.
//
HwDeviceExtension->AdapterDesc.bWtk5x86 = TRUE;
}
//
// Restore the BIOS register to it's original value.
//
VideoDebugPrint((1, "PciGetbaseAddr() about to restore, line %d, status:%x\n", __LINE__, status));
VideoPortSetBusData(HwDeviceExtension,
PCIConfiguration,
HwDeviceExtension->PciSlotNum,
&ulTempAddr,
P9001_BIOS_BASE_ADDR,
sizeof(ULONG));
VideoPortFreeDeviceBase(HwDeviceExtension, (PVOID) pucBiosAddr);
break;
}
}
else if (PciFindDevice(HwDeviceExtension, // Search for a Weitek 9002.
WTK_9002_ID,
WTK_VENDOR_ID,
&HwDeviceExtension->PciSlotNum))
{
wcpID = P9000_ID;
// Now make sure we are looking for a P9000, if were not
// then fail.
if (HwDeviceExtension->P9CoprocInfo.CoprocId != P9000_ID)
{
VideoDebugPrint((1, "PciGetbaseAddr() Failed, not a P9002, line %d\n", __LINE__));
return(FALSE);
}
//
// Found a 9002 board. Set up the table of DAC addresses
// accordingly.
//
DefaultDACRegRange = Pci9002DefDACRegRange;
}
else
{
//
// No Weitek PCI devices were found, return an error.
//
VideoDebugPrint((1, "PciGetbaseAddr() Failed, line %d\n", __LINE__));
return(FALSE);
}
//
// Get the base address of the adapter.
// Some machines rely on the address not changing - if the address changes
// the machine randomly appears to corrupt memory.
// So use the pre-configured address if it is available.
//
HwDeviceExtension->P9PhysAddr.LowPart = 0;
VideoPortGetBusData(HwDeviceExtension,
PCIConfiguration,
HwDeviceExtension->PciSlotNum,
&HwDeviceExtension->P9PhysAddr.LowPart,
P9001_BASE_ADDR,
sizeof(ULONG));
if (HwDeviceExtension->P9PhysAddr.LowPart == 0)
{
IO_RESOURCE_DESCRIPTOR ioResource = {
IO_RESOURCE_PREFERRED,
CmResourceTypeMemory,
CmResourceShareDeviceExclusive,
0,
CM_RESOURCE_MEMORY_READ_WRITE,
0,
{
RESERVE_PCI_ADDRESS_SPACE, // Length
RESERVE_PCI_ADDRESS_SPACE, // Alignment
{ 0x10000000, 0 }, // Minimum start address
{ 0xefffffff, 0} // Maximum end address
}
};
status = VideoPortGetAccessRanges(HwDeviceExtension,
1,
&ioResource,
3,
PciAccessRange,
NULL,
NULL,
&HwDeviceExtension->PciSlotNum);
if (status == NO_ERROR)
{
HwDeviceExtension->P9PhysAddr = PciAccessRange[IO_ACCESS_INDEX].RangeStart;
//
// Save the physical base address in the PCI config space.
//
VideoPortSetBusData(HwDeviceExtension,
PCIConfiguration,
HwDeviceExtension->PciSlotNum,
&HwDeviceExtension->P9PhysAddr.LowPart,
P9001_BASE_ADDR,
sizeof(ULONG));
}
}
if (HwDeviceExtension->P9PhysAddr.LowPart == 0)
{
VideoDebugPrint((1, "PciGetbaseAddr() Failed, line %d\n", __LINE__));
return(FALSE);
}
//
// The P9100 can access the DAC directly, so no I/O space needs to be
// allocated for DAC access.
//
if (wcpID == P9000_ID)
{
status = VideoPortGetAccessRanges(HwDeviceExtension,
0,
NULL,
3,
PciAccessRange,
NULL,
NULL,
&HwDeviceExtension->PciSlotNum);
if (status == NO_ERROR)
{
HwDeviceExtension->P9001PhysicalAddress = PciAccessRange[IO_ACCESS_INDEX].RangeStart;
}
else
{
VideoDebugPrint((1, "VideoPortGetAccessRanges() Failed with status %x, line %d\n", status, __LINE__));
return(FALSE);
}
//
// If this is a 9002 board, map in and read the VGA id register.
//
if (DefaultDACRegRange == Pci9002DefDACRegRange)
{
//
// Set up the access range so we can map out the VGA ID register.
//
PciAccessRange[IO_ACCESS_INDEX].RangeInIoSpace = TRUE;
PciAccessRange[IO_ACCESS_INDEX].RangeVisible = TRUE;
PciAccessRange[IO_ACCESS_INDEX].RangeShareable = TRUE;
PciAccessRange[IO_ACCESS_INDEX].RangeLength = 1;
PciAccessRange[IO_ACCESS_INDEX].RangeStart =
HwDeviceExtension->P9001PhysicalAddress;
PciAccessRange[IO_ACCESS_INDEX].RangeStart.LowPart += P9002_VGA_ID;
//
// Map in the VGA ID register. If it can't be mapped,
// we can't determine the VGA type, so just use the default.
//
if ((pucBoardAddr =
VideoPortGetDeviceBase(HwDeviceExtension,
PciAccessRange[IO_ACCESS_INDEX].RangeStart,
PciAccessRange[IO_ACCESS_INDEX].RangeLength,
PciAccessRange[IO_ACCESS_INDEX].RangeInIoSpace)) != 0)
{
HwDeviceExtension->AdapterDesc.bWtk5x86 =
(UCHAR)((VideoPortReadPortUchar(pucBoardAddr) & VGA_MSK) == WTK_VGA);
VideoPortFreeDeviceBase(HwDeviceExtension,
(PVOID) pucBoardAddr);
}
else
{
//
// Assume this is a 5x86 VGA.
//
HwDeviceExtension->AdapterDesc.bWtk5x86 = TRUE;
}
}
//
// Compute the actual DAC register addresses relative to the PCI
// base address.
//
for (i = 0; i < HwDeviceExtension->Dac.cDacRegs; i++)
{
//
// If this is not a palette addr or data register, and the board
// is not using the standard VL addresses, compute the register
// address relative to the register base address.
//
if ((i > 3) && (DefaultDACRegRange != VLDefDACRegRange))
{
DefaultDACRegRange[i].RangeStart.LowPart +=
HwDeviceExtension->P9001PhysicalAddress.LowPart;
}
}
//
// Copy the DAC register access range into the global list of access
// ranges.
//
VideoPortMoveMemory(&DriverAccessRanges[NUM_DRIVER_ACCESS_RANGES],
DefaultDACRegRange,
sizeof(VIDEO_ACCESS_RANGE) *
HwDeviceExtension->Dac.cDacRegs);
//
// This is a hack. Initialize an additional access range to map out
// the entire 4K range of contiguous IO space starting at PCI_REG_BASE.
// apparently the 9001 decodes accesses over this entire range rather
// than the individual register offsets within this range.
//
//
// Set up the access range so we can map the entire 4k IO range.
//
PciAccessRange[IO_ACCESS_INDEX].RangeInIoSpace = TRUE;
PciAccessRange[IO_ACCESS_INDEX].RangeVisible = TRUE;
PciAccessRange[IO_ACCESS_INDEX].RangeShareable = TRUE;
PciAccessRange[IO_ACCESS_INDEX].RangeLength = P9001_IO_RANGE;
PciAccessRange[IO_ACCESS_INDEX].RangeStart = HwDeviceExtension->P9001PhysicalAddress;
VideoDebugPrint((1, "PciAccessRange[VGABIOS_ACCESS_INDEX].RangeStart.LowPart:%x\n",
PciAccessRange[VGABIOS_ACCESS_INDEX].RangeStart.LowPart));
VideoPortMoveMemory(&DriverAccessRanges[NUM_DRIVER_ACCESS_RANGES +
NUM_DAC_ACCESS_RANGES],
&PciAccessRange[IO_ACCESS_INDEX],
sizeof(VIDEO_ACCESS_RANGE));
} // end of "if (wcpID == P9000_ID)" block.
return(TRUE);
}
BOOLEAN
PciFindDevice(
IN PHW_DEVICE_EXTENSION HwDeviceExtension,
IN USHORT usDeviceId,
IN USHORT usVendorId,
IN OUT PULONG pulSlotNum
)
/*++
Routine Description:
Attempts to find a PCI device which matches the passed device id, vendor
id and index.
Arguments:
HwDeviceExtension - Pointer to the device extension.
usDeviceId - PCI Device Id.
usVendorId - PCI Vendor Id.
pulSlotNum - Input -> Starting Slot Number
Output -> If found, the slot number of the matching device.
Return Value:
TRUE if device found.
--*/
{
ULONG pciBuffer;
PCI_SLOT_NUMBER slotData;
PPCI_COMMON_CONFIG pciData;
//
//
// typedef struct _PCI_SLOT_NUMBER {
// union {
// struct {
// ULONG DeviceNumber:5;
// ULONG FunctionNumber:3;
// ULONG Reserved:24;
// } bits;
// ULONG AsULONG;
// } u;
// } PCI_SLOT_NUMBER, *PPCI_SLOT_NUMBER;
//
slotData.u.AsULONG = 0;
pciData = (PPCI_COMMON_CONFIG) &pciBuffer;
//
// Look at each device.
//
*pulSlotNum = 0;
slotData.u.bits.DeviceNumber = *pulSlotNum;
slotData.u.bits.FunctionNumber = 0;
if (VideoPortGetBusData(HwDeviceExtension,
PCIConfiguration,
slotData.u.AsULONG,
(PVOID) pciData,
0,
sizeof(ULONG)) == 0)
{
//
// Out of functions. Go to next PCI bus.
//
return(FALSE);
}
if (pciData->VendorID == PCI_INVALID_VENDORID)
{
//
// No PCI device, or no more functions on device
// move to next PCI device.
//
return(FALSE);
}
if (pciData->VendorID == usVendorId &&
pciData->DeviceID == usDeviceId)
{
*pulSlotNum = slotData.u.AsULONG;
return(TRUE);
}
//
// No matching PCI device was found.
//
return(FALSE);
}
BOOLEAN
PciP9MemEnable(
PHW_DEVICE_EXTENSION HwDeviceExtension
)
/*++
Routine Description:
Enable the physical memory and IO resources for PCI adapters.
Arguments:
HwDeviceExtension - Pointer to the miniport driver's device extension.
Return Value:
None.
--*/
{
ULONG ulTemp;
//
// Read the PCI command register to determine if the memory/io
// resources are enabled. If not, enable them.
//
if (!VideoPortGetBusData(HwDeviceExtension,
PCIConfiguration,
HwDeviceExtension->PciSlotNum,
&ulTemp,
P9001_CMD_REG,
sizeof(ulTemp)))
{
return(FALSE);
}
else if (!(ulTemp & (P9001_MEM_ENB | P9001_IO_ENB)))
{
ulTemp |= (P9001_MEM_ENB | P9001_IO_ENB);
if (!VideoPortSetBusData(HwDeviceExtension,
PCIConfiguration,
HwDeviceExtension->PciSlotNum,
&ulTemp,
P9001_CMD_REG,
sizeof(ulTemp)))
{
return(FALSE);
}
}
return(TRUE);
}
VOID
ViperPciP9Enable(
PHW_DEVICE_EXTENSION HwDeviceExtension
)
/*++
Routine Description:
Perform the OEM specific tasks necessary to enable the P9. These
include memory mapping, setting the sync polarities, and enabling the
P9 video output.
Arguments:
HwDeviceExtension - Pointer to the miniport driver's device extension.
Return Value:
None.
--*/
{
USHORT holdit;
//
// Select external frequency, and clear the polarity bits.
//
holdit = VGA_RD_REG(MISCIN) | (MISCD | MISCC);
holdit &= ~(VIPER_HSYNC_POL_MASK | VIPER_VSYNC_POL_MASK);
//
// Viper controls h and v sync polarities independently.
//
if (HwDeviceExtension->VideoData.vp == POSITIVE)
{
holdit |= VIPER_VSYNC_POL_MASK;
}
if (HwDeviceExtension->VideoData.hp == POSITIVE)
{
holdit |= VIPER_HSYNC_POL_MASK;
}
VGA_WR_REG(MISCOUT, holdit);
//
// If this is a Weitek VGA, unlock the VGA.
//
if (HwDeviceExtension->AdapterDesc.bWtk5x86)
{
UnlockVGARegs(HwDeviceExtension);
}
//
// Enable P9 Video.
//
VGA_WR_REG(SEQ_INDEX_PORT, SEQ_OUTCNTL_INDEX);
VGA_WR_REG(SEQ_DATA_PORT, (VGA_RD_REG(SEQ_DATA_PORT)) | P9_VIDEO_ENB);
//
// If this is a Weitek VGA, lock the VGA sequencer registers.
//
if (HwDeviceExtension->AdapterDesc.bWtk5x86)
{
LockVGARegs(HwDeviceExtension);
}
return;
}
BOOLEAN
ViperPciP9Disable(
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
--*/
{
//
// Unlock the VGA extended regs to disable P9 video output.
//
//
// If this is a Weitek VGA, unlock the VGA.
//
if (HwDeviceExtension->AdapterDesc.bWtk5x86)
{
UnlockVGARegs(HwDeviceExtension);
}
VGA_WR_REG(SEQ_INDEX_PORT, SEQ_OUTCNTL_INDEX);
VGA_WR_REG(SEQ_DATA_PORT, (VGA_RD_REG(SEQ_DATA_PORT)) & P9_VIDEO_DIS);
//
// Restore clock select bits.
//
VGA_WR_REG(MISCOUT, HwDeviceExtension->MiscRegState);
//
// If this is a Weitek VGA, lock the VGA sequencer registers.
//
if (HwDeviceExtension->AdapterDesc.bWtk5x86)
{
LockVGARegs(HwDeviceExtension);
}
return TRUE;
}