|
|
/*++
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; }
|