1252 lines
42 KiB
C
1252 lines
42 KiB
C
/*++
|
||
|
||
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;
|
||
}
|